Work
This commit is contained in:
parent
217e03e86a
commit
07bd583b0d
11 changed files with 255 additions and 18 deletions
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
OUTNAME = flisp
|
OUTNAME = flisp
|
||||||
|
|
||||||
CFLAGS = -O0 -Wall -Wextra -g -pipe
|
CFLAGS = -O0 -Wall -Wextra -g -pipe -Wno-cast-function-type
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
|
|
14
TODO.md
Normal file
14
TODO.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
- Load files
|
||||||
|
- Benchmarks
|
||||||
|
- Tests
|
||||||
|
- Assign on declaration
|
||||||
|
- Rework assign/call to work better
|
||||||
|
- Finish internal allocator
|
||||||
|
- Strings
|
||||||
|
- String casts
|
||||||
|
- Core functions
|
||||||
|
- Type checks
|
||||||
|
- Scopes
|
||||||
|
|
||||||
|
- Type propagation
|
||||||
|
- Bytecode gen
|
6
examples/1p1.flsp
Normal file
6
examples/1p1.flsp
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
(var a)
|
||||||
|
(var b)
|
||||||
|
(a 1)
|
||||||
|
(b 1)
|
||||||
|
(write (+ a b))
|
||||||
|
(newline)
|
|
@ -86,6 +86,13 @@ typedef struct {
|
||||||
|
|
||||||
} PACKED ValueArray;
|
} PACKED ValueArray;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
// Cast to a 48bit FnSig ptr
|
||||||
|
u8 __raw_bytes[6];
|
||||||
|
|
||||||
|
} PACKED ValueFn;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
PACKED union {
|
PACKED union {
|
||||||
|
@ -102,6 +109,7 @@ typedef struct {
|
||||||
Value4B v4B;
|
Value4B v4B;
|
||||||
ValueArray varray;
|
ValueArray varray;
|
||||||
ValueStr vstr;
|
ValueStr vstr;
|
||||||
|
ValueFn vfn;
|
||||||
};
|
};
|
||||||
|
|
||||||
Tag tag;
|
Tag tag;
|
||||||
|
@ -124,6 +132,12 @@ typedef struct {
|
||||||
} FnSig;
|
} FnSig;
|
||||||
|
|
||||||
#ifndef win
|
#ifndef win
|
||||||
//_Static_assert(sizeof(Value) == 8);
|
_Static_assert(sizeof(Value) == 8);
|
||||||
#endif
|
#endif
|
||||||
_Static_assert(sizeof(Tag) <= sizeof(i32));
|
_Static_assert(sizeof(Tag) <= sizeof(i32));
|
||||||
|
|
||||||
|
static inline FnSig *get_fnsig(Value *x){
|
||||||
|
u64 rval = *((u64*)x);
|
||||||
|
rval &= 0xFFFFFFFFFFFF; // 48bits - should be (mostly) fine
|
||||||
|
return (void*)rval;
|
||||||
|
}
|
||||||
|
|
|
@ -89,4 +89,4 @@ typedef struct {
|
||||||
|
|
||||||
} ASTStack;
|
} ASTStack;
|
||||||
|
|
||||||
_Static_assert(BI_assign >= ST__end);
|
_Static_assert((int)BI_assign >= ST__end);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
@ -6,11 +7,25 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "code_defs.h"
|
#include "code_defs.h"
|
||||||
#include "byte_defs.h"
|
#include "byte_defs.h"
|
||||||
|
#include "exec_common.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
u32 pos;
|
||||||
|
u32 size;
|
||||||
|
|
||||||
|
} AllocBlock;
|
||||||
|
|
||||||
|
void *internal_buf;
|
||||||
|
AllocBlock *blocks;
|
||||||
|
u32 *usage; // bitmap for usage, by 8byte chunks
|
||||||
|
size_t internal_size;
|
||||||
|
u32 block_count;
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
|
|
||||||
void runtime_err(char *s){
|
void runtime_err(char *s){
|
||||||
printf("Runtime Error : %s\n", s);
|
fprintf(stderr,"Runtime Error : %s\n", s);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +50,61 @@ int evaluate(Value val){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int alloc_init(){
|
||||||
|
internal_buf = malloc(4096);
|
||||||
|
printf("55\n");
|
||||||
|
blocks = malloc(sizeof(AllocBlock));
|
||||||
|
printf("57\n");
|
||||||
|
block_count = 0;
|
||||||
|
usage = malloc(sizeof(u32)*4096/32/8);
|
||||||
|
printf("60\n");
|
||||||
|
if(!internal_buf || !blocks || !usage)
|
||||||
|
return 1;
|
||||||
|
memset(usage, 0, sizeof(u32)*4096/32/8);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 flisp_alloc(size_t size){
|
||||||
|
u32 pos = 32;
|
||||||
|
u32 curr_free = 0;
|
||||||
|
while(pos < internal_size){
|
||||||
|
if(usage[pos/32/8]){
|
||||||
|
for(int i = 0; i < 32; i++){
|
||||||
|
if((usage[pos/32/8]>>i) & 1)
|
||||||
|
curr_free = 0;
|
||||||
|
else
|
||||||
|
curr_free+=8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
curr_free += 32*8;
|
||||||
|
}
|
||||||
|
if(curr_free >= size){
|
||||||
|
blocks = realloc(blocks, sizeof(AllocBlock)*(block_count+1));
|
||||||
|
if(!blocks)
|
||||||
|
return 0;
|
||||||
|
AllocBlock *block = &blocks[block_count++];
|
||||||
|
block->pos = pos - curr_free;
|
||||||
|
block->size = size;
|
||||||
|
for(u32 i = block->pos; i < block->pos+size; i++){
|
||||||
|
usage[i/32/8] |= 1<<(i%(32*8));
|
||||||
|
}
|
||||||
|
memset(get_addr(block->pos),0xB0B69420,size);
|
||||||
|
return block->pos;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flisp_free(u32 pos){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void *get_addr(u32 pos){
|
||||||
|
return internal_buf + pos;
|
||||||
|
}
|
||||||
|
|
||||||
// Lesser special functions
|
// Lesser special functions
|
||||||
|
|
||||||
Value is(Tag tag, Value b){
|
Value is(Tag tag, Value b){
|
||||||
|
@ -43,8 +113,85 @@ Value is(Tag tag, Value b){
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value cast(Tag type, Value b){
|
typedef Value (cast_fn_t)(Value);
|
||||||
|
|
||||||
|
Value int_to_fix(Value x){
|
||||||
|
x.tag.type = T_fix;
|
||||||
|
x.v4B.value = fix(x.v4B.value);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value int_to_flt(Value x){
|
||||||
|
x.tag.type = T_float;
|
||||||
|
x.v4B.vfl = (float)x.v4B.value;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value fix_to_int(Value x){
|
||||||
|
x.tag.type = T_int;
|
||||||
|
x.v4B.value = ffloor(x.v4B.value);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value fix_to_flt(Value x){
|
||||||
|
x.tag.type = T_float;
|
||||||
|
x.v4B.vfl = f2float(x.v4B.value);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value flt_to_int(Value x){
|
||||||
|
x.tag.type = T_int;
|
||||||
|
x.v4B.value = (i32)(x.v4B.vfl);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value flt_to_fix(Value x){
|
||||||
|
x.tag.type = T_fix;
|
||||||
|
x.v4B.value = fixfloat(x.v4B.vfl);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value int_to_str(Value x){
|
||||||
|
runtime_err("TODO : int_to_str");
|
||||||
|
}
|
||||||
|
|
||||||
|
Value fix_to_str(Value x){
|
||||||
|
runtime_err("TODO : fix_to_str");
|
||||||
|
}
|
||||||
|
|
||||||
|
Value flt_to_str(Value x){
|
||||||
|
runtime_err("TODO : flt_to_str");
|
||||||
|
}
|
||||||
|
|
||||||
|
Value str_to_int(Value x){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Value str_to_fix(Value x){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Value str_to_flt(Value x){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// [from][to]
|
||||||
|
cast_fn_t *cast_table[4][4] = {
|
||||||
|
{NULL , int_to_fix, int_to_flt, int_to_str},
|
||||||
|
{fix_to_int, NULL , fix_to_flt, fix_to_str},
|
||||||
|
{flt_to_int, flt_to_fix, NULL , flt_to_str},
|
||||||
|
{str_to_int, str_to_fix, str_to_flt, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
Value cast(Tag type, Value b){
|
||||||
|
if(type.type == b.tag.type)
|
||||||
|
return b;
|
||||||
|
if(type.type == T_null || b.tag.type == T_null || type.type == T_fn
|
||||||
|
|| b.tag.type == T_fn || type.is_array || b.tag.is_array){
|
||||||
|
b.tag.type = T_null;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return cast_table[b.tag.type-1][type.type-1](b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic builtins
|
// Generic builtins
|
||||||
|
@ -219,16 +366,20 @@ Value write(Value a){
|
||||||
printf("%f",a.v4B.vfl);
|
printf("%f",a.v4B.vfl);
|
||||||
break;
|
break;
|
||||||
case T_str:
|
case T_str:
|
||||||
|
// TODO replace strdup
|
||||||
|
char *nstr;
|
||||||
if(a.vstr.len > 4){
|
if(a.vstr.len > 4){
|
||||||
runtime_err("Not implem");
|
char *str = get_addr(a.vstr.pos);
|
||||||
|
nstr = strndup(str, a.vstr.len);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
char *nstr = strndup(a.vstr.str, 4);
|
nstr = strndup(a.vstr.str, 4);
|
||||||
nstr[a.vstr.len] = '\0';
|
}
|
||||||
printf("%s",nstr);
|
printf("%s",nstr);
|
||||||
free(nstr);
|
free(nstr);
|
||||||
}
|
break;
|
||||||
case T_fn:
|
case T_fn:
|
||||||
|
printf("<fn @%lx>", (u64)get_fnsig(&a));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,10 +4,22 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
void runtime_err(char *s);
|
void runtime_err(char *s);
|
||||||
|
|
||||||
int evaluate(Value val);
|
int evaluate(Value val);
|
||||||
|
|
||||||
|
int alloc_init();
|
||||||
|
|
||||||
|
// All internal allocator memory is guaranteed to be free range and 32bit
|
||||||
|
u32 flisp_alloc(size_t size);
|
||||||
|
|
||||||
|
void flisp_free(u32 pos);
|
||||||
|
|
||||||
|
void *flisp_realloc(u32 pos, size_t size);
|
||||||
|
|
||||||
|
void *get_addr(u32 pos);
|
||||||
|
|
||||||
Value is(Tag tag, Value b);
|
Value is(Tag tag, Value b);
|
||||||
|
|
||||||
void symbol_map_add_bi(HashMap *map);
|
void symbol_map_add_bi(HashMap *map);
|
||||||
|
|
|
@ -61,7 +61,7 @@ Value execute(Statement *stat){
|
||||||
FnSig *fn = stat->func;
|
FnSig *fn = stat->func;
|
||||||
Statement **params;
|
Statement **params;
|
||||||
if(fn->n_param)
|
if(fn->n_param)
|
||||||
params = ((Statement*)stat->children[0])->children;
|
params = (Statement**)((Statement*)stat->children[0])->children;
|
||||||
if(fn->is_builtin){
|
if(fn->is_builtin){
|
||||||
switch(fn->n_param){
|
switch(fn->n_param){
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "byte_defs.h"
|
#include "byte_defs.h"
|
||||||
#include "code_defs.h"
|
#include "code_defs.h"
|
||||||
|
#include "exec_common.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
|
@ -53,6 +54,10 @@ Statement *make_iconst(i32 val){
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Statement *make_strconst(char *str){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Statement *declare(i32 type, Tag vtype, char *name){
|
Statement *declare(i32 type, Tag vtype, char *name){
|
||||||
i32 len = strcspn(name, " \t\n)");
|
i32 len = strcspn(name, " \t\n)");
|
||||||
char *name2 = strndup(name, len);
|
char *name2 = strndup(name, len);
|
||||||
|
@ -87,6 +92,7 @@ Statement *make_block(Statement *first){
|
||||||
stat->type = ST_Block;
|
stat->type = ST_Block;
|
||||||
stat->children = malloc(sizeof(void*));
|
stat->children = malloc(sizeof(void*));
|
||||||
stat->children[0] = first;
|
stat->children[0] = first;
|
||||||
|
first->parent = stat;
|
||||||
stat->child_n = 1;
|
stat->child_n = 1;
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
@ -94,6 +100,7 @@ Statement *make_block(Statement *first){
|
||||||
Statement *add_block(Statement *block, Statement *add){
|
Statement *add_block(Statement *block, Statement *add){
|
||||||
block->children = realloc(block->children, sizeof(void*)*(block->child_n+1));
|
block->children = realloc(block->children, sizeof(void*)*(block->child_n+1));
|
||||||
block->children[block->child_n++] = add;
|
block->children[block->child_n++] = add;
|
||||||
|
add->parent = block;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +141,8 @@ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){
|
||||||
stat->func = fnsig;
|
stat->func = fnsig;
|
||||||
}
|
}
|
||||||
if(nparam){
|
if(nparam){
|
||||||
|
if(!fnsig)
|
||||||
|
yyerror("Calling function that has not been specified");
|
||||||
if(param->child_n > fnsig->n_param)
|
if(param->child_n > fnsig->n_param)
|
||||||
yyerror("Too many parameters to function");
|
yyerror("Too many parameters to function");
|
||||||
}
|
}
|
||||||
|
@ -145,12 +154,15 @@ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){
|
||||||
|
|
||||||
stat->type = type;
|
stat->type = type;
|
||||||
|
|
||||||
if(nparam)
|
if(nparam){
|
||||||
stat->children[stat->child_n++] = param;
|
stat->children[stat->child_n++] = param;
|
||||||
|
param->parent = stat;
|
||||||
|
}
|
||||||
// TODO : Type checks
|
// TODO : Type checks
|
||||||
for(int i = 1; i < nparam; i++){
|
for(int i = 1; i < nparam; i++){
|
||||||
Statement *prm_n = va_arg(prm, Statement*);
|
Statement *prm_n = va_arg(prm, Statement*);
|
||||||
stat->children[stat->child_n++] = prm_n;
|
stat->children[stat->child_n++] = prm_n;
|
||||||
|
prm_n->parent = stat;
|
||||||
}
|
}
|
||||||
va_end(prm);
|
va_end(prm);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
#.+\n ;
|
||||||
|
|
||||||
":vec" return VEC;
|
":vec" return VEC;
|
||||||
|
|
||||||
|
@ -26,6 +27,11 @@
|
||||||
"block" return BLOCK;
|
"block" return BLOCK;
|
||||||
"is" return IS;
|
"is" return IS;
|
||||||
|
|
||||||
|
\"[^"\n]*["\n] {
|
||||||
|
yylval.st = make_strconst(yytext+1);
|
||||||
|
printf("STRCST : %s\n",yytext);
|
||||||
|
return CST;
|
||||||
|
}
|
||||||
|
|
||||||
[-+*/%<=>!a-zA-Z]+ {
|
[-+*/%<=>!a-zA-Z]+ {
|
||||||
yylval.str = yytext;
|
yylval.str = yytext;
|
||||||
|
|
28
src/parser.y
28
src/parser.y
|
@ -1,10 +1,12 @@
|
||||||
%{
|
%{
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "code_defs.h"
|
#include "code_defs.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
#include "exec_common.h"
|
||||||
|
|
||||||
int yylex();
|
int yylex();
|
||||||
%}
|
%}
|
||||||
|
@ -34,7 +36,8 @@
|
||||||
%%
|
%%
|
||||||
|
|
||||||
program:
|
program:
|
||||||
expr_list ';' {execute($1); exit(0); }
|
expr_list ';' {execute($1);}
|
||||||
|
| expr_list YYEOF {execute($1);}
|
||||||
;
|
;
|
||||||
|
|
||||||
type:
|
type:
|
||||||
|
@ -117,9 +120,28 @@ void yyerror(char *s){
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(){
|
extern FILE *yyin;
|
||||||
printf("fLisp interactive env - v0.1\nFcalva 2025\nUnder the terms of the GPL v3.0 license\n");
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
alloc_init();
|
||||||
|
|
||||||
|
if(argc < 2){
|
||||||
|
printf("fLisp interactive env - v0.1\nFcalva 2025\n");
|
||||||
|
printf("Under the terms of the GPL v3.0 license\n");
|
||||||
|
yyin = stdin;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
yyin = fopen(argv[1], "r");
|
||||||
|
if(!yyin){
|
||||||
|
fprintf(stderr,"Failed to open file \"%s\"", argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
make_stack();
|
make_stack();
|
||||||
yyparse();
|
yyparse();
|
||||||
|
|
||||||
|
fclose(yyin);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue