From 97bc549d4b8bf638946ac4ff3b066941bca9a03b Mon Sep 17 00:00:00 2001 From: rodri Date: Thu, 5 Sep 2024 15:45:27 +0000 Subject: initial compiler work. --- alloc.c | 43 ++++++++++++ builtin.c | 90 +++++++++++++++++++++++++ dat.h | 47 ++++++++++++++ fns.h | 12 ++++ mkfile | 17 +++++ semblance.y | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sym.c | 33 ++++++++++ test.shader | 10 +++ 8 files changed, 465 insertions(+) create mode 100644 alloc.c create mode 100644 builtin.c create mode 100644 dat.h create mode 100644 fns.h create mode 100644 mkfile create mode 100644 semblance.y create mode 100644 sym.c create mode 100644 test.shader diff --git a/alloc.c b/alloc.c new file mode 100644 index 0000000..afd57bc --- /dev/null +++ b/alloc.c @@ -0,0 +1,43 @@ +#include +#include + +void * +emalloc(ulong n) +{ + void *p; + + p = malloc(n); + if(p == nil) + sysfatal("malloc: %r"); + setmalloctag(p, getcallerpc(&n)); + return p; +} + +void * +erealloc(void *p, ulong n) +{ + void *np; + + np = realloc(p, n); + if(np == nil){ + if(n == 0) + return nil; + sysfatal("realloc: %r"); + } + if(p == nil) + setmalloctag(np, getcallerpc(&p)); + else + setrealloctag(np, getcallerpc(&p)); + return np; +} + +char * +estrdup(char *s) +{ + char *ns; + + ns = strdup(s); + if(ns == nil) + sysfatal("strdup: %r"); + return ns; +} diff --git a/builtin.c b/builtin.c new file mode 100644 index 0000000..ae7821e --- /dev/null +++ b/builtin.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include "dat.h" +#include "fns.h" +#include "y.tab.h" + +static char *types[] = { + "double", + "point", + "vector", + "normal", + "quat", +}; + +static char *ctypes[] = { + "double", + "Point3", + "Point3", + "Point3", + "Quaternion", +}; + +static Const consts[] = { + "π", 3.14159265358979323846, + "e", 2.71828182845904523536, + "γ", 0.57721566490153286060, + "DEG", 57.29577951308232087680, + "Φ", 1.61803398874989484820, +}; + +static Builtin builtins[] = { + "sin", sin, + "cos", cos, + "atan", atan, + "atan2", atan2, + "log", log, + "log10", log10, + "exp", exp, + "sqrt", sqrt, + "int", round, + "abs", fabs, +}; + +double +round(double n) +{ + return floor(n + 0.5); +} + +int +lookuptype(char *s) +{ + int i; + + for(i = 0; i < nelem(types); i++) + if(strcmp(s, types[i]) == 0) + return i; + return -1; +} + +char * +typename(int t) +{ + if(t >= 0 && t < nelem(types)) + return types[t]; + return nil; +} + +char * +ctypename(int t) +{ + if(t >= 0 && t < nelem(ctypes)) + return ctypes[t]; + return nil; +} + +void +init(void) +{ + Symbol *s; + int i; + + for(i = 0; i < nelem(consts); i++) + install(consts[i].name, CONST, consts[i].val); + for(i = 0; i < nelem(builtins); i++){ + s = install(builtins[i].name, BLTIN, 0); + s->u.fn = builtins[i].fn; + } +} diff --git a/dat.h b/dat.h new file mode 100644 index 0000000..052270f --- /dev/null +++ b/dat.h @@ -0,0 +1,47 @@ +enum +{ + TDOUBLE, + TPOINT, + TVECTOR, + TNORMAL, + TQUAT, +}; + +typedef struct Var Var; +typedef struct Symbol Symbol; +typedef struct Const Const; +typedef struct Builtin Builtin; + +struct Var +{ + int type; + union { + double dval; + Point3 pval; + Quaternion qval; + }; +}; + +struct Symbol +{ + char *name; + int type; + union { + Var var; + double val; /* constant value */ + double (*fn)(double); + } u; + Symbol *next; +}; + +struct Const +{ + char *name; + double val; +}; + +struct Builtin +{ + char *name; + double (*fn)(); +}; diff --git a/fns.h b/fns.h new file mode 100644 index 0000000..ddc80be --- /dev/null +++ b/fns.h @@ -0,0 +1,12 @@ +Symbol *install(char*, int, double); +Symbol *lookup(char*); +double round(double); +int lookuptype(char*); +char* typename(int); +char* ctypename(int); +void init(void); +void *emalloc(ulong); +void *erealloc(void*, ulong); +char *estrdup(char*); + +int yyparse(void); diff --git a/mkfile b/mkfile new file mode 100644 index 0000000..c69651a --- /dev/null +++ b/mkfile @@ -0,0 +1,17 @@ + +#include +#include +#include +#include +#include "dat.h" +#include "fns.h" +%} +%union { + int type; + double val; + Symbol *sym; +} +%token TYPE +%token NUMBER +%token VAR CONST BLTIN UNDEF +%type expr exprs +%type asgn asgns +%right '=' +%% +top: /* ε */ + | list + ; +list: prog + | list prog + ; +prog: '\n' + | decls + | asgns + | exprs { print("\t%.8g\n", $1); } + ; +decls: decls decl + | decl + ; +decl: TYPE { decltype = $1; } vars ';' + ; +vars: VAR + { + if($1->type != UNDEF) + rterror("variable already exists"); + + $1->type = VAR; + $1->u.var.type = decltype; + print("%s %s;\n", ctypename(decltype), $1->name); + } + | vars ',' VAR + { + if($3->type != UNDEF) + rterror("variable already exists"); + + $3->type = VAR; + $3->u.var.type = decltype; + print("%s %s;\n", ctypename(decltype), $3->name); + } + ; +asgns: asgns asgn ';' + | asgn ';' + ; +asgn: VAR '=' NUMBER + { + if($1->type != VAR || $1->u.var.type != TDOUBLE) + rterror("illegal assignment"); + + $1->u.var.dval = $3; + $$ = $1; + } + | VAR '=' VAR + { + switch($1->type){ + default: rterror("illegal assignment"); + case VAR: + if($1->u.var.type != $3->u.var.type) + rterror("illegal assignment"); + + switch($1->u.var.type){ + case TDOUBLE: + $1->u.var.dval = $3->u.var.dval; + break; + case TPOINT: + case TVECTOR: + case TNORMAL: + case TQUAT: + $1->u.var.pval = $3->u.var.pval; + break; + } + $$ = $1; + break; + } + } + ; +exprs: exprs expr ';' + | expr ';' + ; +expr: NUMBER + | VAR + { + Point3 *p; + + switch($1->type){ + case UNDEF: rterror("undefined variable"); + case CONST: $$ = $1->u.val; break; + case VAR: + switch($1->u.var.type){ + case TDOUBLE: $$ = $1->u.var.dval; break; + case TPOINT: + case TVECTOR: + case TNORMAL: + $$ = -1; + p = &$1->u.var.pval; + print("[%g %g %g %g]\n", p->x, p->y, p->z, p->w); + break; + } + break; + } + } + ; +%% + +int decltype; +Biobuf *bin; +int lineno; + +void +yyerror(char *msg) +{ + fprint(2, "%s at line %d\n", msg, lineno); +} + +void +rterror(char *msg) +{ + fprint(2, "%s at line %d\n", msg, lineno); +} + +int +yylex(void) +{ + Symbol *s; + char sname[256], *p; + Rune r; + int t; + + while((r = Bgetrune(bin)) == ' ' || r == '\t') + ; + + if(r == Beof) + return 0; + + if(r == '.' || isdigitrune(r)){ + Bungetrune(bin); + Bgetd(bin, &yylval.val); + return NUMBER; + } + + if(isalpharune(r)){ + p = sname; + + do{ + if(p+runelen(r) - sname >= sizeof(sname)) + return r; /* force syntax error. */ + p += runetochar(p, &r); + }while((r = Bgetrune(bin)) != Beof && + (isalpharune(r) || isdigitrune(r))); + Bungetrune(bin); + *p = 0; + + if((t = lookuptype(sname)) >= 0){ + yylval.type = t; + return TYPE; + } + + if((s = lookup(sname)) == nil) + s = install(sname, UNDEF, 0); + yylval.sym = s; + + return s->type == UNDEF || s->type == CONST ? VAR : s->type; + } + + if(r == '\n') + lineno++; + + return r; +} + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + ARGBEGIN{ + default: usage(); + }ARGEND; + if(argc > 0) + usage(); + + bin = Bfdopen(0, OREAD); + if(bin == nil) + sysfatal("Bfdopen: %r"); + + lineno++; + init(); + + yyparse(); + + Bterm(bin); + exits(nil); +} diff --git a/sym.c b/sym.c new file mode 100644 index 0000000..d84fec5 --- /dev/null +++ b/sym.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include "dat.h" +#include "fns.h" + +static Symbol *symtab; + +Symbol * +install(char *s, int t, double v) +{ + Symbol *sym; + + sym = emalloc(sizeof(Symbol)); + memset(sym, 0, sizeof *sym); + sym->name = estrdup(s); + sym->type = t; + sym->u.val = v; + sym->next = symtab; + symtab = sym; + return sym; +} + +Symbol * +lookup(char *s) +{ + Symbol *sym; + + for(sym = symtab; sym != nil; sym = sym->next) + if(strcmp(sym->name, s) == 0) + return sym; + return nil; +} diff --git a/test.shader b/test.shader new file mode 100644 index 0000000..4b79a8d --- /dev/null +++ b/test.shader @@ -0,0 +1,10 @@ +point a, b; +double n; + +n = 1; +n; + +a + b; +a * n; +n * b; +n * n; -- cgit v1.2.3