shithub: hammer

Download patch

ref: 4457deb19fb16af77ee0f0f8b3ea745b3fe41e1d
parent: e01f61f0d55b37630264e8d74107199752a6e76f
author: Jacob Moody <moody@posixcafe.org>
date: Fri Apr 26 02:55:03 EDT 2024

enough to generate basic c programs

--- a/dat.h
+++ b/dat.h
@@ -78,6 +78,7 @@
 	Oinc,
 	Odec,
 	Orcv,
+	Oind,
 };
 
 enum {
@@ -157,6 +158,7 @@
 #pragma	   varargck    type  "O"   Nod*
 #pragma	   varargck    type  "L"   Nlst
 #pragma	   varargck    type  "M"   Nlst
+#pragma	   varargck    type  "P"   Nlst
 
 extern int	lexline;
 extern char*	lexfile;
--- a/fmt.c
+++ b/fmt.c
@@ -28,7 +28,7 @@
 	[Orcv]	"←"
 };
 
-static char tabs[128];
+static char tabs[128], stars[128];
 
 int
 nodfmt(Fmt *f)
@@ -67,6 +67,8 @@
 	case Nexpr:
 		if(n->expr.op == Olit || n->expr.op == Ovar)
 			return fmtprint(f, "%N", n->expr.lhs);
+		else if(n->expr.op == Oind)
+			return fmtprint(f, "%N[%N]", n->expr.lhs, n->expr.rhs);
 		else
 			return fmtprint(f, "EXPR(%N %s %N)", n->expr.lhs, expoptab[n->expr.op], n->expr.rhs);
 	case Nblk:
@@ -103,7 +105,9 @@
 cnodfmt(Fmt *f)
 {
 	Nod *n;
+	char *t;
 	int nt, e;
+	Typ *ty;
 
 	nt = f->prec;
 	n = va_arg(f->args, Nod*);
@@ -134,6 +138,8 @@
 	case Nexpr:
 		if(n->expr.op == Olit || n->expr.op == Ovar)
 			return fmtprint(f, "%O", n->expr.lhs);
+		else if(n->expr.op == Oind)
+			return fmtprint(f, "%N[%N]", n->expr.lhs, n->expr.rhs);
 		else
 			return fmtprint(f, "%O %s %O", n->expr.lhs, expoptab[n->expr.op], n->expr.rhs);
 	case Nblk:
@@ -140,11 +146,19 @@
 		e = nt - 1;
 		if(e < 0)
 			e = 0;
-		return fmtprint(f, "{\n%.*M\n%.*s}", nt, n->blk.body, e, tabs);
+		return fmtprint(f, "{\n%.*P\n%.*s}", nt, n->blk.body, e, tabs);
 	case Ndcl:
-		return fmtprint(f, "%s %s", n->dcl.type->name, n->dcl.name);
+		e = 0;
+		for(ty = n->dcl.type; ty->t == Tslice; ty = ty->base)
+			e++;
+		return fmtprint(f, "%s %.*s%s", ty->name, e, stars, n->dcl.name);
 	case Nfunc:
-		return fmtprint(f, "void\n%s(%M)\n%.*O", n->func.name, n->func.args, nt+1, n->func.body);
+		t = n->func.type->base->name;
+		if(n->func.args.nv == 0)
+			fmtprint(f, "%s\n%s(void)", t, n->func.name);
+		else
+			fmtprint(f, "%s\n%s(%M)", t, n->func.name, n->func.args);
+		return fmtprint(f, "\n%.*O",  nt+1, n->func.body);
 	case Ncall:
 		return fmtprint(f, "%s(%M)", n->call.name, n->call.args);
 	}
@@ -166,13 +180,36 @@
 	return 0;
 }
 
+int
+cnlstfmtblk(Fmt *f)
+{
+	int i, nt;
+	Nlst n;
+
+	nt = f->prec;
+	n = va_arg(f->args, Nlst);
+	for(i = 0; i < n.nv; i++){
+		fmtprint(f, "%.*O", nt, n.v[i]);
+		switch(n.v[i]->t){
+		case Ncall: case Ndcl: case Nexpr:
+			fmtprint(f, ";");
+		}
+		if(i != n.nv-1)
+			fmtprint(f, "\n");
+	}
+	return 0;
+}
+
 void
 astfmtinstall(void)
 {
 	memset(tabs, '\t', nelem(tabs)-1);
 	tabs[nelem(tabs)-1] = '\0';
+	memset(stars, '*', nelem(stars)-1);
+	tabs[nelem(stars)-1] = '\0';
 	fmtinstall('N', nodfmt);
 	fmtinstall('L', nlstfmt);
 	fmtinstall('O', cnodfmt);
 	fmtinstall('M', cnlstfmt);
+	fmtinstall('P', cnlstfmtblk);
 }
--- a/n.y
+++ b/n.y
@@ -35,9 +35,9 @@
 }
 
 %token FUNC DEF IF FOR MOD USE OR AND NOTEQ EQ SHIFTL SHIFTR STRUCT ELSE ARROWR ARROWL GTEQ LTEQ INC DEC
-%token TYPE NAME NUM
+%token TYPE NAME NUM STR
 
-%token	<sval>	NAME;
+%token	<sval>	NAME STR
 %token	<ival>	NUM
 
 %type<nod>	defarg expr logexpr shifexpr addexpr mulexpr
@@ -84,7 +84,8 @@
 unary
 :	NUM			{ $$ = mkexpr(Olit, mkintlit($1), nil); }
 |	NAME			{ $$ = mkexpr(Ovar, mksym($1), nil); }
-|	'"' NAME '"'		{ $$ = mkstrlit($2); }
+|	STR			{ $$ = mkstrlit($1); }
+|	NAME '[' NUM ']'	{ $$ = mkexpr(Oind, mksym($1), mkintlit($3)); }
 |	'(' expr ')'		{ $$ = $2; }
 
 sufexpr
@@ -215,6 +216,27 @@
 }
 
 void
+strlex(char *dst, int n)
+{
+	Rune c;
+	char *e;
+
+	for(e = dst + n - UTFmax; dst < e;){
+		c = getch();
+		if((c >= Runeself)
+		|| (c != '"' && c != '\n')){
+			dst += runetochar(dst, &c);
+			continue;
+		}
+		ungetc();
+		break;
+	}
+	if(dst > e - UTFmax*2)
+		yyerror("symbol buffer overrun");
+	*dst = '\0';
+}
+
+void
 yyerror(char *s)
 {
 	fprint(2, "%d: %s\n", lexline, s);
@@ -284,8 +306,14 @@
 		if(getch() == '/')
 			goto Loop;
 		goto More;
+	case '"':
+		strlex(buf, sizeof buf);
+		if(getch() != '"')
+			yyerror("non terminated string");
+		yylval.sval = strdup(buf);
+		return STR;
 	}
-	if(utfrune("\"';{}[]()*/%:,.", c) != nil)
+	if(utfrune("';{}[]()*/%:,.", c) != nil)
 		return c;
 	for(i = 0; i < nelem(spectab); i++){
 		if(c != spectab[i].c)
@@ -358,10 +386,13 @@
 		usage();
 		break;
 	}ARGEND;
-	if(argc > 0)
+	if(argc > 1)
 		usage();
 	astfmtinstall();
-	bin = Bfdopen(0, OREAD);
+	if(argc == 0)
+		bin = Bfdopen(0, OREAD);
+	else
+		bin = Bopen(argv[0], OREAD);
 	goteof = 0;
 	while(!goteof)
 		yyparse();
@@ -369,6 +400,6 @@
 	if(ast)
 		print("%L\n", toplevel);
 	else
-		print("%M\n", toplevel);
+		print("#include <u.h>\n#include <libc.h>\n\n%P\n", toplevel);
 	exits(nil);
 }