summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2024-09-05 15:45:27 +0000
committerrodri <rgl@antares-labs.eu>2024-09-05 15:45:27 +0000
commit97bc549d4b8bf638946ac4ff3b066941bca9a03b (patch)
tree5bd5ca788c8e3577dda001e0454157c9408ac08f
parent11087295a24b0a8d08897824c7ee9676026fa159 (diff)
downloadsemblance-97bc549d4b8bf638946ac4ff3b066941bca9a03b.tar.gz
semblance-97bc549d4b8bf638946ac4ff3b066941bca9a03b.tar.bz2
semblance-97bc549d4b8bf638946ac4ff3b066941bca9a03b.zip
initial compiler work.
-rw-r--r--alloc.c43
-rw-r--r--builtin.c90
-rw-r--r--dat.h47
-rw-r--r--fns.h12
-rw-r--r--mkfile17
-rw-r--r--semblance.y213
-rw-r--r--sym.c33
-rw-r--r--test.shader10
8 files changed, 465 insertions, 0 deletions
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 <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;
+ }
+}
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 @@
+</$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);
+}
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 <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;