diff options
-rw-r--r-- | alloc.c | 43 | ||||
-rw-r--r-- | builtin.c | 90 | ||||
-rw-r--r-- | dat.h | 47 | ||||
-rw-r--r-- | fns.h | 12 | ||||
-rw-r--r-- | mkfile | 17 | ||||
-rw-r--r-- | semblance.y | 213 | ||||
-rw-r--r-- | sym.c | 33 | ||||
-rw-r--r-- | test.shader | 10 |
8 files changed, 465 insertions, 0 deletions
@@ -0,0 +1,43 @@ +#include <u.h> +#include <libc.h> + +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 <u.h> +#include <libc.h> +#include <geometry.h> +#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; + } +} @@ -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)(); +}; @@ -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); @@ -0,0 +1,17 @@ +</$objtype/mkfile + +BIN=/$objtype/bin +TARG=sslc +OFILES=\ + alloc.$O\ + sym.$O\ + builtin.$O\ + y.tab.$O +YFILES=\ + semblance.y +HFILES=\ + dat.h\ + fns.h\ + y.tab.h + +</sys/src/cmd/mkone diff --git a/semblance.y b/semblance.y new file mode 100644 index 0000000..c6629a1 --- /dev/null +++ b/semblance.y @@ -0,0 +1,213 @@ +%{ +#include <u.h> +#include <libc.h> +#include <ctype.h> +#include <bio.h> +#include <geometry.h> +#include "dat.h" +#include "fns.h" +%} +%union { + int type; + double val; + Symbol *sym; +} +%token <type> TYPE +%token <val> NUMBER +%token <sym> VAR CONST BLTIN UNDEF +%type <val> expr exprs +%type <sym> 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); +} @@ -0,0 +1,33 @@ +#include <u.h> +#include <libc.h> +#include <geometry.h> +#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; |