From 226bfe84c5f690462adbf386dc66316cc21fdb28 Mon Sep 17 00:00:00 2001 From: crupest Date: Mon, 22 Nov 2021 20:53:01 +0800 Subject: import(life): Add compile principle codes. --- works/life/compile-principle-experiment/1/hoc.y | 65 +++++++++++++ works/life/compile-principle-experiment/1/makefile | 5 + works/life/compile-principle-experiment/2/hoc.y | 106 +++++++++++++++++++++ works/life/compile-principle-experiment/2/makefile | 5 + 4 files changed, 181 insertions(+) create mode 100644 works/life/compile-principle-experiment/1/hoc.y create mode 100644 works/life/compile-principle-experiment/1/makefile create mode 100644 works/life/compile-principle-experiment/2/hoc.y create mode 100644 works/life/compile-principle-experiment/2/makefile (limited to 'works/life/compile-principle-experiment') diff --git a/works/life/compile-principle-experiment/1/hoc.y b/works/life/compile-principle-experiment/1/hoc.y new file mode 100644 index 0000000..c4452ad --- /dev/null +++ b/works/life/compile-principle-experiment/1/hoc.y @@ -0,0 +1,65 @@ +%{ +#define YYSTYPE double /* data type of yacc stack */ +#include +#include +#include + +int yylex(); +int yyerror(const char * s); +%} +%token NUMBER +%left '+' '-' /* left associative, same precedence */ +%left '*' '/' '%' /* left assoc., higher precedence */ +%left UNARYMINUS +%% +list: /* nothing */ + | list '\n' + | list expr '\n' { printf("%lf\n", $2); } + ; +expr: NUMBER { $$ = $1; } + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr { $$ = $1 / $3; } + | expr '%' expr { $$ = fmod($1, $3); } + | '-' expr %prec UNARYMINUS { $$ = -$2; } + | '(' expr ')' { $$ = $2; } + ; +%% + +int lineno = 1; + +int main(int argc, char** argv) +{ + yyparse(); + return 0; +} + +int yylex() +{ + int c; + + do { + c = getchar(); + } while (c == ' ' || c == '\t'); + + if (c == EOF) + return 0; + + if (c == '.' || isdigit(c)) { + ungetc(c, stdin); + scanf("%lf", &yylval); + return NUMBER; + } + + if (c == '\n') + lineno++; + + return c; +} + +int yyerror(const char* s) +{ + fprintf(stderr, "Error occured near line %d\n", lineno); + return 0; +} diff --git a/works/life/compile-principle-experiment/1/makefile b/works/life/compile-principle-experiment/1/makefile new file mode 100644 index 0000000..65bcca2 --- /dev/null +++ b/works/life/compile-principle-experiment/1/makefile @@ -0,0 +1,5 @@ +hoc: hoc.c + cc hoc.c -o hoc + +hoc.c: hoc.y + bison hoc.y -o hoc.c diff --git a/works/life/compile-principle-experiment/2/hoc.y b/works/life/compile-principle-experiment/2/hoc.y new file mode 100644 index 0000000..14500bb --- /dev/null +++ b/works/life/compile-principle-experiment/2/hoc.y @@ -0,0 +1,106 @@ +%{ +#include +#include +#include + +int yylex(); +int yyerror(const char * s); +void execerror(const char* s, const char* t); +void warning(const char* s, const char* t); + +double mem[26]; /* memory for variables 'a'..'z' */ +%} + +%union { /* stack type */ + double val; /* actual value */ + int index; /* index into mem[] */ +} +%token NUMBER +%token VAR +%type expr +%right '=' +%left '+' '-' +%left '*' '/' +%left UNARYMINUS +%% +list: /* nothing */ + | list '\n' + | list expr '\n' { printf("\t%.8g\n", $2); } + | list error '\n' { yyerrok; } + ; +expr: NUMBER + | VAR { $$ = mem[$1]; } + | VAR '=' expr { $$ = mem[$1] = $3; } + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr { + if ($3 == 0.0) + execerror("division by zero", ""); + $$ = $1 / $3; } + | '(' expr ')' { $$ = $2; } + | '-' expr %prec UNARYMINUS { $$ = -$2; } + ; +%% + /* end of grammar */ + +int lineno = 1; +#include +#include +jmp_buf begin; + +void fpecatch(int s); + +int main(int argc, char** argv) +{ + (void)setjmp(begin); + signal(SIGFPE, fpecatch); + yyparse(); +} + +int yylex() +{ + int c; + + while ((c=getchar()) == ' ' || c == '\t') + ; + if (c == EOF) + return 0; + if (c == '.' || isdigit(c)) { /* number */ + ungetc(c, stdin); + scanf("%lf", &yylval.val); + return NUMBER; + } + if (islower(c)) { + yylval.index = c - 'a'; /* ASCII only */ + return VAR; + } + if (c == '\n') + lineno++; + return c; +} + +int yyerror(const char *s) +{ + warning(s, (char *)0); + return 0; +} + +void execerror(const char* s, const char* t) +{ + warning(s, t); + longjmp(begin, 0); +} + +void fpecatch(int s) +{ + execerror("floating point exception", (char *) 0); +} + +void warning(const char* s, const char* t) +{ + fprintf(stderr, "%s", s); + if (t && *t) + fprintf(stderr, " %s", t); + fprintf(stderr, " near line %d\n", lineno); +} diff --git a/works/life/compile-principle-experiment/2/makefile b/works/life/compile-principle-experiment/2/makefile new file mode 100644 index 0000000..65bcca2 --- /dev/null +++ b/works/life/compile-principle-experiment/2/makefile @@ -0,0 +1,5 @@ +hoc: hoc.c + cc hoc.c -o hoc + +hoc.c: hoc.y + bison hoc.y -o hoc.c -- cgit v1.2.3 From 1ea48b1fcb7ac64935018b1ced2d0f11982872ea Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 24 Nov 2021 20:43:52 +0800 Subject: import(life): Add compile principle experiment 3. --- works/life/compile-principle-experiment/3/lex.l | 17 ++++ works/life/compile-principle-experiment/3/main.c | 107 +++++++++++++++++++++ works/life/compile-principle-experiment/3/main.h | 25 +++++ works/life/compile-principle-experiment/3/makefile | 22 +++++ works/life/compile-principle-experiment/3/syn.y | 42 ++++++++ works/life/main.cpp | 36 ------- works/life/test.ipynb | 49 ++++++++++ 7 files changed, 262 insertions(+), 36 deletions(-) create mode 100644 works/life/compile-principle-experiment/3/lex.l create mode 100644 works/life/compile-principle-experiment/3/main.c create mode 100644 works/life/compile-principle-experiment/3/main.h create mode 100644 works/life/compile-principle-experiment/3/makefile create mode 100644 works/life/compile-principle-experiment/3/syn.y delete mode 100644 works/life/main.cpp create mode 100644 works/life/test.ipynb (limited to 'works/life/compile-principle-experiment') diff --git a/works/life/compile-principle-experiment/3/lex.l b/works/life/compile-principle-experiment/3/lex.l new file mode 100644 index 0000000..ddea92d --- /dev/null +++ b/works/life/compile-principle-experiment/3/lex.l @@ -0,0 +1,17 @@ +%{ +#include "main.h" +#include "syn.h" +%} +%option noyywrap +%% +[ \t] { ; } /* skip blanks and tabs */ +[0-9]+\.?|[0-9]*\.[0-9]+ { + sscanf(yytext, "%lf", &yylval.val); return NUMBER; } +[a-zA-Z][a-zA-Z0-9]* { + Symbol *s; + if ((s=cru_symbol_lookup(yytext)) == 0) + s = cru_symbol_install(yytext, UNDEF, (SymbolValue)0.0); + yylval.sym = s; + return s->type == UNDEF ? VAR : s->type; } +\n { lineno++; return '\n'; } /* everything else */ +. { return yytext[0]; } diff --git a/works/life/compile-principle-experiment/3/main.c b/works/life/compile-principle-experiment/3/main.c new file mode 100644 index 0000000..7cd8c28 --- /dev/null +++ b/works/life/compile-principle-experiment/3/main.c @@ -0,0 +1,107 @@ +#include "main.h" + +#include "syn.h" + +#include +#include +#include +#include +#include +#include + +static Symbol *symlist = 0; /* symbol table: linked list */ + +void *emalloc(size_t n) /* check return from malloc */ +{ + void *p = malloc(n); + if (p == 0) + execerror("out of memory", (char *)0); + return p; +} + +Symbol *cru_symbol_lookup(const char *name) { + for (Symbol *sp = symlist; sp != NULL; sp = sp->next) + if (strcmp(sp->name, name) == 0) + return sp; + return NULL; +} + +Symbol *cru_symbol_install(const char *name, int type, SymbolValue value) { + Symbol *sp = (Symbol *)emalloc(sizeof(Symbol)); + sp->name = emalloc(strlen(name) + 1); + strcpy(sp->name, name); + sp->type = type; + sp->value = value; + sp->next = symlist; + symlist = sp; + return sp; +} + +jmp_buf begin; +int lineno; + +void warning(const char *s, const char *t) { + fprintf(stderr, "%s", s); + if (t) + fprintf(stderr, " %s", t); + fprintf(stderr, " near line %d\n", lineno); +} + +void yyerror(const char *s) { warning(s, NULL); } + +void execerror(const char *s, const char *t) { + warning(s, t); + longjmp(begin, 0); +} + +double errcheck(double result, const char *name) { + if (errno == EDOM) { + errno = 0; + execerror(name, "argument out of domain"); + } else if (errno == ERANGE) { + errno = 0; + execerror(name, "result out of range"); + } + return result; +} + +double Log(double x) { return errcheck(log(x), "log"); } +double Log10(double x) { return errcheck(log10(x), "log10"); } +double Sqrt(double x) { return errcheck(sqrt(x), "sqrt"); } +double Exp(double x) { return errcheck(exp(x), "exp"); } +double Pow(double x, double y) { return errcheck(pow(x, y), "exponentiation"); } +double integer(double x) { return (double)(long)x; } + +static struct { /* Constants */ + char *name; + double cval; +} consts[] = { + {"PI", 3.14159265358979323846}, {"E", 2.71828182845904523536}, + {"GAMMA", 0.57721566490153286060}, {"DEG", 57.29577951308232087680}, + {"PHI", 1.61803398874989484820}, +}; + +static struct { /* Built-ins */ + char *name; + double (*func)(); +} builtins[] = { + {"sin", sin}, {"cos", cos}, {"atan", atan}, + {"log", Log}, {"log10", Log10}, {"exp", Exp}, + {"sqrt", Sqrt}, {"int", integer}, {"abs", fabs}, +}; + +void init() { + for (int i = 0; i < sizeof(consts) / sizeof(*consts); i++) + cru_symbol_install(consts[i].name, VAR, (SymbolValue)consts[i].cval); + for (int i = 0; i < sizeof(builtins) / sizeof(*builtins); i++) { + cru_symbol_install(builtins[i].name, BLTIN, (SymbolValue)builtins->func); + } +} + +int main(int argc, char **argv) { + init(); + (void)setjmp(begin); + yyparse(); + + return 0; +} diff --git a/works/life/compile-principle-experiment/3/main.h b/works/life/compile-principle-experiment/3/main.h new file mode 100644 index 0000000..9bd6e56 --- /dev/null +++ b/works/life/compile-principle-experiment/3/main.h @@ -0,0 +1,25 @@ +#pragma once + +typedef union SymbolValue { + double val; + double (*ptr)(); +} SymbolValue; + +typedef struct Symbol { + char *name; + int type; + SymbolValue value; + struct Symbol *next; +} Symbol; + +Symbol *cru_symbol_lookup(const char *name); +Symbol *cru_symbol_install(const char *name, int type, SymbolValue value); + +double Pow(double x, double y); + +int yylex(); +int yyparse(); +void yyerror(const char *s); + +extern int lineno; +void execerror(const char *s, const char *t); diff --git a/works/life/compile-principle-experiment/3/makefile b/works/life/compile-principle-experiment/3/makefile new file mode 100644 index 0000000..cf6333c --- /dev/null +++ b/works/life/compile-principle-experiment/3/makefile @@ -0,0 +1,22 @@ +main: main.o lex.o syn.o + cc lex.o syn.o main.o -o main + +main.o: main.c main.h syn.h + cc -c -o main.o main.c + +lex.c: lex.l + flex -o lex.c lex.l + +lex.o: lex.c syn.h main.h + cc -c -o lex.o lex.c + +syn.c syn.h: syn.y + bison syn.y -d -o syn.c + +syn.o: syn.c syn.h main.h + cc -c -o syn.o syn.c + +PHONY: clean + +clean: + rm -f *.o lex.c syn.c syn.h main diff --git a/works/life/compile-principle-experiment/3/syn.y b/works/life/compile-principle-experiment/3/syn.y new file mode 100644 index 0000000..80abb17 --- /dev/null +++ b/works/life/compile-principle-experiment/3/syn.y @@ -0,0 +1,42 @@ +%{ +#include "main.h" +#include +%} +%union { + double val; /* actual value */ + Symbol *sym; /* symbol table pointer */ +} +%token NUMBER +%token VAR BLTIN UNDEF +%type expr asgn +%right '=' +%left '+' '-' +%left '*' '/' +%left UNARYMINUS +%right '^' /* exponentiation */ +%% +list: /* nothing */ + | list '\n' + | list asgn '\n' + | list expr '\n' { printf("\t%.8g\n", $2); } + | list error '\n' { yyerrok; } + ; +asgn: VAR '=' expr { $$=$1->value.val=$3; $1->type = VAR; } + ; +expr: NUMBER + | VAR { if ($1->type == UNDEF) + execerror("undefined variable", $1->name); + $$ = $1->value.val; } + | BLTIN '(' expr ')' { $$ = (*($1->value.ptr))($3); } + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr { + if ($3 == 0.0) + execerror("division by zero", ""); + $$ = $1 / $3; } + | expr '^' expr { $$ = Pow($1, $3); } + | '(' expr ')' { $$ = $2; } + | '-' expr %prec UNARYMINUS { $$ = -$2; } + ; +%% diff --git a/works/life/main.cpp b/works/life/main.cpp deleted file mode 100644 index efb5bff..0000000 --- a/works/life/main.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include -#include -#include - -std::wstring ToString(const SOCKET_ADDRESS &addr) { - DWORD buffer_length = 100; - wchar_t buffer[100]; - auto error = WSAAddressToStringW(addr.lpSockaddr, addr.iSockaddrLength, NULL, - buffer, &buffer_length); - assert(error == 0); - return std::wstring(buffer); -} - -int main() { - WSADATA wsaData; - int error = WSAStartup(MAKEWORD(2, 0), &wsaData); - assert(error == 0); - - ULONG buffer_size = 100000; - PIP_ADAPTER_ADDRESSES_LH buffer = - (PIP_ADAPTER_ADDRESSES_LH)malloc(buffer_size); - ULONG error2 = GetAdaptersAddresses( - AF_INET, - GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS | - GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_SKIP_MULTICAST, - NULL, buffer, &buffer_size); - assert(error2 == ERROR_SUCCESS); - - std::wcout << ToString(buffer->FirstPrefix->Address) << L"\n"; - std::wcout << buffer->FirstGatewayAddress << L"\n"; - - return 0; -} diff --git a/works/life/test.ipynb b/works/life/test.ipynb new file mode 100644 index 0000000..7536d4b --- /dev/null +++ b/works/life/test.ipynb @@ -0,0 +1,49 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tensor(6)\n" + ] + } + ], + "source": [ + "import torch\n", + "\n", + "t = torch.tensor([1, 2, 3]);\n", + "print(t.sum())\n" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" + }, + "kernelspec": { + "display_name": "Python 3.9.9 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.9" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} -- cgit v1.2.3 From 27556004e8e12a72ed1c2c70212f6b660ed798c3 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 2 Dec 2021 21:59:36 +0800 Subject: import(life): ... --- works/life/compile-principle-experiment/4/lex.l | 20 ++ works/life/compile-principle-experiment/4/main.c | 279 +++++++++++++++++++++ works/life/compile-principle-experiment/4/main.h | 41 +++ works/life/compile-principle-experiment/4/makefile | 22 ++ works/life/compile-principle-experiment/4/syn.y | 39 +++ 5 files changed, 401 insertions(+) create mode 100644 works/life/compile-principle-experiment/4/lex.l create mode 100644 works/life/compile-principle-experiment/4/main.c create mode 100644 works/life/compile-principle-experiment/4/main.h create mode 100644 works/life/compile-principle-experiment/4/makefile create mode 100644 works/life/compile-principle-experiment/4/syn.y (limited to 'works/life/compile-principle-experiment') diff --git a/works/life/compile-principle-experiment/4/lex.l b/works/life/compile-principle-experiment/4/lex.l new file mode 100644 index 0000000..e7731ca --- /dev/null +++ b/works/life/compile-principle-experiment/4/lex.l @@ -0,0 +1,20 @@ +%{ +#include "main.h" +#include "syn.h" +%} +%option noyywrap +%% +[ \t] { ; } /* skip blanks and tabs */ +[0-9]+\.?|[0-9]*\.[0-9]+ { + Symbol *s = cru_symbol_install("", UNDEF, (SymbolValue)0.0); + sscanf(yytext, "%lf", &s->value.val); + yylval.sym = s; + return NUMBER; } +[a-zA-Z][a-zA-Z0-9]* { + Symbol *s; + if ((s=cru_symbol_lookup(yytext)) == 0) + s = cru_symbol_install(yytext, UNDEF, (SymbolValue)0.0); + yylval.sym = s; + return s->type == UNDEF ? VAR : s->type; } +\n { lineno++; return '\n'; } /* everything else */ +. { return yytext[0]; } diff --git a/works/life/compile-principle-experiment/4/main.c b/works/life/compile-principle-experiment/4/main.c new file mode 100644 index 0000000..258ccc7 --- /dev/null +++ b/works/life/compile-principle-experiment/4/main.c @@ -0,0 +1,279 @@ +#include "main.h" + +#include "syn.h" + +#include +#include +#include +#include +#include +#include + +static Symbol *symlist = 0; /* symbol table: linked list */ + +void *emalloc(size_t n) /* check return from malloc */ +{ + void *p = malloc(n); + if (p == 0) + execerror("out of memory", (char *)0); + return p; +} + +Symbol *cru_symbol_lookup(const char *name) { + for (Symbol *sp = symlist; sp != NULL; sp = sp->next) + if (strcmp(sp->name, name) == 0) + return sp; + return NULL; +} + +Symbol *cru_symbol_install(const char *name, int type, SymbolValue value) { + Symbol *sp = (Symbol *)emalloc(sizeof(Symbol)); + sp->name = emalloc(strlen(name) + 1); + strcpy(sp->name, name); + sp->type = type; + sp->value = value; + sp->next = symlist; + symlist = sp; + return sp; +} + +jmp_buf begin; +int lineno; + +void warning(const char *s, const char *t) { + fprintf(stderr, "%s", s); + if (t) + fprintf(stderr, " %s", t); + fprintf(stderr, " near line %d\n", lineno); +} + +void yyerror(const char *s) { warning(s, NULL); } + +void execerror(const char *s, const char *t) { + warning(s, t); + longjmp(begin, 0); +} + +double errcheck(double result, const char *name) { + if (errno == EDOM) { + errno = 0; + execerror(name, "argument out of domain"); + } else if (errno == ERANGE) { + errno = 0; + execerror(name, "result out of range"); + } + return result; +} + +double Log(double x) { return errcheck(log(x), "log"); } +double Log10(double x) { return errcheck(log10(x), "log10"); } +double Sqrt(double x) { return errcheck(sqrt(x), "sqrt"); } +double Exp(double x) { return errcheck(exp(x), "exp"); } +double Pow(double x, double y) { return errcheck(pow(x, y), "exponentiation"); } +double integer(double x) { return (double)(long)x; } + +static struct { /* Constants */ + char *name; + double cval; +} consts[] = { + {"PI", 3.14159265358979323846}, {"E", 2.71828182845904523536}, + {"GAMMA", 0.57721566490153286060}, {"DEG", 57.29577951308232087680}, + {"PHI", 1.61803398874989484820}, +}; + +static struct { /* Built-ins */ + char *name; + double (*func)(); +} builtins[] = { + {"sin", sin}, {"cos", cos}, {"atan", atan}, + {"log", Log}, {"log10", Log10}, {"exp", Exp}, + {"sqrt", Sqrt}, {"int", integer}, {"abs", fabs}, +}; + +int initcode(); +int execute(Inst *p); + +void init() { + initcode(); + for (int i = 0; i < sizeof(consts) / sizeof(*consts); i++) + cru_symbol_install(consts[i].name, VAR, (SymbolValue)consts[i].cval); + for (int i = 0; i < sizeof(builtins) / sizeof(*builtins); i++) { + cru_symbol_install(builtins[i].name, BLTIN, (SymbolValue)builtins->func); + } +} + +int main(int argc, char **argv) { + init(); + (void)setjmp(begin); + yyparse(); + execute(prog); + + return 0; +} + +#define NSTACK 256 +static Datum stack[NSTACK]; /* the stack */ +static Datum *stackp; /* next free spot on stack */ + +#define NPROG 2000 +Inst prog[NPROG]; /* the machine */ +Inst *progp; /* next free spot for code generation */ +Inst *pc; /* program counter during execution */ + +int initcode() /* initialize for code generation */ +{ + stackp = stack; + progp = prog; + return 0; +} + +int push(Datum d) /* push d onto stack */ +{ + if (stackp >= &stack[NSTACK]) + execerror("stack overflow", (char *)0); + *stackp++ = d; + return 0; +} + +Datum pop() /* pop and return top elem from stack */ +{ + if (stackp <= stack) + execerror("stack underflow", (char *)0); + return *--stackp; +} + +int constpush() /* push constant onto stack */ +{ + Datum d; + d.val = ((Symbol *)*pc++)->value.val; + push(d); + return 0; +} + +int varpush() /* push variable onto stack */ +{ + Datum d; + d.sym = (Symbol *)(*pc++); + push(d); + return 0; +} + +int bltin() /* evaluate built-in on top of stack */ +{ + Datum d; + d = pop(); + d.val = (*(double (*)())(*pc++))(d.val); + push(d); + return 0; +} + +int eval() /* evaluate variable on stack */ +{ + Datum d; + d = pop(); + if (d.sym->type == UNDEF) + execerror("undefined variable", d.sym->name); + d.val = d.sym->value.val; + push(d); + return 0; +} + +int add() /* add top two elems on stack */ +{ + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val += d2.val; + push(d1); + return 0; +} + +int sub() /* subtract top of stack from next */ +{ + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val -= d2.val; + push(d1); + return 0; +} + +int mul() { + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val *= d2.val; + push(d1); + return 0; +} + +int mydiv() { + Datum d1, d2; + d2 = pop(); + if (d2.val == 0.0) + execerror("division by zero", (char *)0); + d1 = pop(); + d1.val /= d2.val; + push(d1); + return 0; +} + +int negate() { + Datum d; + d = pop(); + d.val = -d.val; + push(d); + return 0; +} + +int power() { + Datum d1, d2; + extern double Pow(); + d2 = pop(); + d1 = pop(); + d1.val = Pow(d1.val, d2.val); + push(d1); + return 0; +} + +int assign() /* assign top value to next value */ +{ + Datum d1, d2; + d1 = pop(); + d2 = pop(); + if (d1.sym->type != VAR && d1.sym->type != UNDEF) + execerror("assignment to non-variable", d1.sym->name); + d1.sym->value.val = d2.val; + d1.sym->type = VAR; + push(d2); + return 0; +} + +int print() /* pop top value from stack, print it */ +{ + Datum d; + d = pop(); + printf("\t%.8g\n", d.val); + return 0; +} + +Inst *code(Inst f) /* install one instruction or operand */ +{ + Inst *oprogp = progp; + if (progp >= &prog[NPROG]) + execerror("program too big", (char *)0); + *progp++ = f; + return oprogp; +} + +int execute(Inst *p) /* run the machine */ +{ + for (pc = p; *pc != STOP;) + (*(*pc++))(); + return 0; +} + +int mypop() { + pop(); + return 0; +} diff --git a/works/life/compile-principle-experiment/4/main.h b/works/life/compile-principle-experiment/4/main.h new file mode 100644 index 0000000..96bd9e7 --- /dev/null +++ b/works/life/compile-principle-experiment/4/main.h @@ -0,0 +1,41 @@ +#pragma once + +typedef union SymbolValue { + double val; + double (*ptr)(); +} SymbolValue; + +typedef struct Symbol { + char *name; + int type; + SymbolValue value; + struct Symbol *next; +} Symbol; + +Symbol *cru_symbol_lookup(const char *name); +Symbol *cru_symbol_install(const char *name, int type, SymbolValue value); + +double Pow(double x, double y); + +int yylex(); +int yyparse(); +void yyerror(const char *s); + +extern int lineno; +void execerror(const char *s, const char *t); + +typedef union Datum { /* interpreter stack type */ + double val; + Symbol *sym; +} Datum; +extern Datum pop(); +int mypop(); + +typedef int (*Inst)(); /* machine instruction */ +#define STOP (Inst)0 + +extern Inst prog[]; +extern int eval(), add(), sub(), mul(), mydiv(), negate(), power(); +extern int assign(), bltin(), varpush(), constpush(), print(); + +extern Inst *code(Inst f); diff --git a/works/life/compile-principle-experiment/4/makefile b/works/life/compile-principle-experiment/4/makefile new file mode 100644 index 0000000..756cdcb --- /dev/null +++ b/works/life/compile-principle-experiment/4/makefile @@ -0,0 +1,22 @@ +main: main.o lex.o syn.o + cc -g lex.o syn.o main.o -o main + +main.o: main.c main.h syn.h + cc -g -c -o main.o main.c + +lex.c: lex.l + flex -o lex.c lex.l + +lex.o: lex.c syn.h main.h + cc -g -c -o lex.o lex.c + +syn.c syn.h: syn.y + bison syn.y -d -o syn.c + +syn.o: syn.c syn.h main.h + cc -g -c -o syn.o syn.c + +PHONY: clean + +clean: + rm -f *.o lex.c syn.c syn.h main diff --git a/works/life/compile-principle-experiment/4/syn.y b/works/life/compile-principle-experiment/4/syn.y new file mode 100644 index 0000000..ebe113f --- /dev/null +++ b/works/life/compile-principle-experiment/4/syn.y @@ -0,0 +1,39 @@ +%{ +#include "main.h" +#include +#define code2(c1,c2) code(c1); code(c2) +#define code3(c1,c2,c3) code(c1); code(c2); code(c3) +%} +%union { + Symbol *sym; /* symbol table pointer */ + double val; + Inst *inst; /* machine instruction */ +} +%token NUMBER VAR BLTIN UNDEF +%right '=' +%left '+' '-' +%left '*' '/' +%left UNARYMINUS +%right '^' /* exponentiation */ +%% +list: /* nothing */ + | list '\n' + | list asgn '\n' { code2(mypop, STOP); return 1; } + | list expr '\n' { code2(print, STOP); return 1; } + | list error '\n' { yyerrok; } + ; +asgn: VAR '=' expr { code3(varpush,(Inst)$1,assign); } + ; +expr: NUMBER { code2(constpush, (Inst)$1); } + | VAR { code3(varpush, (Inst)$1, eval); } + | asgn + | BLTIN '(' expr ')' { code2(bltin, (Inst)$1->value.ptr); } + | '(' expr ')' + | expr '+' expr { code(add); } + | expr '-' expr { code(sub); } + | expr '*' expr { code(mul); } + | expr '/' expr { code(mydiv); } + | expr '^' expr { code(power); } + | '-' expr %prec UNARYMINUS { code(negate); } + ; +%% -- cgit v1.2.3