Start on llvm IR target
This commit is contained in:
parent
f798fbe55f
commit
c54a158d78
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/it0-out0.diff
|
||||
/it1-out*
|
||||
/it2-out*
|
||||
/it3-out*
|
||||
|
||||
36
Makefile
36
Makefile
@ -40,30 +40,54 @@ it2-out0.py: it1-out.py it2-in.lang0
|
||||
# No gcc step since the target is still python here
|
||||
|
||||
it2-out1.c: it2-out0.py it2-in.lang0
|
||||
cat it2-in.lang0 | python3 it2-out0.py > it2-out1.c
|
||||
cat it2-in.lang0 | python3 it2-out0.py > $@
|
||||
# diff it2-out0.py it2-out1.py Do not diff - the target changed so the output will be different
|
||||
|
||||
it2-out1: it2-out1.c
|
||||
gcc it2-out1.c -o it2-out1 $(GCC_FLAGS)
|
||||
gcc $^ -o $@ $(GCC_FLAGS)
|
||||
|
||||
it2-out2.c: it2-out1 it2-in.lang0
|
||||
cat it2-in.lang0 | ./it2-out1 > it2-out2.c
|
||||
diff it2-out1.c it2-out2.c
|
||||
cat it2-in.lang0 | ./it2-out1 > $@
|
||||
diff it2-out1.c $@
|
||||
|
||||
it2-out2: it2-out2.c
|
||||
gcc it2-out2.c -o it2-out2 $(GCC_FLAGS)
|
||||
gcc $^ -o $@ $(GCC_FLAGS)
|
||||
|
||||
it2-out3.c: it2-out2 it2-in.lang0
|
||||
cat it2-in.lang0 | ./it2-out2 > it2-out3.c
|
||||
diff it2-out2.c it2-out3.c
|
||||
|
||||
it2-out3: it2-out3.c
|
||||
gcc it2-out3.c -o it2-out3 $(GCC_FLAGS)
|
||||
gcc $^ -o $@ $(GCC_FLAGS)
|
||||
|
||||
it2-out: it2-out3
|
||||
cp it2-out3 it2-out
|
||||
|
||||
|
||||
|
||||
it3-out0.c: it2-out it3-in.lang0
|
||||
cat it3-in.lang0 | ./it2-out > it3-out0.c
|
||||
|
||||
# gcc step since the target is still python here
|
||||
it3-out0: it3-out0.c
|
||||
gcc $^ -o $@ $(GCC_FLAGS)
|
||||
|
||||
it3-out1.ll: it3-out0 it3-in.lang0
|
||||
cat it3-in.lang0 | ./it3-out0 > $@
|
||||
|
||||
it3-out1.s: it3-out1.ll
|
||||
llc $^ -o $@
|
||||
|
||||
|
||||
|
||||
foo.ll: foo.c
|
||||
clang -S -emit-llvm $^
|
||||
|
||||
foo.s: foo.ll
|
||||
llc $^
|
||||
|
||||
foo: foo.s
|
||||
clang $^ -o $@
|
||||
|
||||
clean:
|
||||
-rm it1-out* it2-out*
|
||||
|
||||
36
README.md
36
README.md
@ -113,6 +113,42 @@ Creates a new string with `b` appended to `a`.
|
||||
|
||||
Writes the given string to standard output.
|
||||
|
||||
#### fileget path
|
||||
|
||||
Reads a file named `path` from the current directory into a string.
|
||||
|
||||
#### intinc a
|
||||
|
||||
Available in it2 runtime and onwards.
|
||||
|
||||
Interprets string `a` as an integer, increases it by one and returns it (as a string).
|
||||
If `a` cannot be interpreted as an integer, or has additional bytes, this function returns 1.
|
||||
|
||||
#### mapclear mapname
|
||||
|
||||
Available in it2 runtime and onwards.
|
||||
|
||||
Maps are global and can be used from any function.
|
||||
|
||||
Clears all values set in the map named `mapname`.
|
||||
|
||||
#### mapgetkey mapname key
|
||||
|
||||
Available in it2 runtime and onwards.
|
||||
|
||||
Maps are global and can be used from any function.
|
||||
|
||||
Looks up `key` in the map named `mapname` and returns it.
|
||||
If not found, returns an empty string.
|
||||
|
||||
#### mapsetkey mapname key value
|
||||
|
||||
Available in it2 runtime and onwards.
|
||||
|
||||
Maps are global and can be used from any function.
|
||||
|
||||
Adds a mapping from `key` to `value` to the map named `mapname`.
|
||||
|
||||
#### peek
|
||||
|
||||
Checks stdin for the next character and returns it.
|
||||
|
||||
17
foo.c
Normal file
17
foo.c
Normal file
@ -0,0 +1,17 @@
|
||||
void print(char * x)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int sum(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char * foo = "Hello, world!";
|
||||
print("This is a test.");
|
||||
|
||||
return sum(7, 15);
|
||||
}
|
||||
2
it0-in-footer.py
Normal file
2
it0-in-footer.py
Normal file
@ -0,0 +1,2 @@
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
51
it0-in-header.py
Normal file
51
it0-in-header.py
Normal file
@ -0,0 +1,51 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
def eq(a, b):
|
||||
return a == b
|
||||
|
||||
def lt(a, b):
|
||||
return a[0] < b[0]
|
||||
|
||||
def addstringchar(a, b):
|
||||
return a + b[0]
|
||||
|
||||
def emit(string):
|
||||
sys.stdout.write(string)
|
||||
|
||||
def trace(header, value):
|
||||
if os.environ.get('TRACE'):
|
||||
sys.stderr.write(f'{header}={value!r}\\n')
|
||||
|
||||
eof = chr(0)
|
||||
eol = chr(10)
|
||||
quote = chr(34)
|
||||
PEEK = None
|
||||
LINE = 1
|
||||
|
||||
def peek():
|
||||
global PEEK
|
||||
if PEEK is None:
|
||||
char = sys.stdin.read(1)
|
||||
trace('char', char)
|
||||
if not char:
|
||||
PEEK = eof
|
||||
else:
|
||||
PEEK = char
|
||||
return PEEK
|
||||
|
||||
def skip():
|
||||
global LINE
|
||||
global PEEK
|
||||
if eol == PEEK:
|
||||
LINE += 1
|
||||
PEEK = None
|
||||
|
||||
def skipchar(char):
|
||||
global LINE
|
||||
assert char == peek(), (LINE, char, peek())
|
||||
skip()
|
||||
|
||||
def fileget(path):
|
||||
with open(f'./{path}', encoding='ASCII') as fil:
|
||||
return fil.read()
|
||||
58
it0-out.py
58
it0-out.py
@ -41,6 +41,10 @@ def skipchar(char):
|
||||
assert char == peek(), (LINE, char, peek())
|
||||
skip()
|
||||
|
||||
def fileget(path):
|
||||
with open(f'./{path}', encoding='ASCII') as fil:
|
||||
return fil.read()
|
||||
|
||||
def lexident():
|
||||
word = ''
|
||||
while True:
|
||||
@ -280,58 +284,12 @@ def parsefunc():
|
||||
emit("\n")
|
||||
|
||||
def emitheader():
|
||||
emit("import os\n")
|
||||
emit("import sys\n")
|
||||
emit("\n")
|
||||
emit("def eq(a, b):\n")
|
||||
emit(" return a == b\n")
|
||||
emit("\n")
|
||||
emit("def lt(a, b):\n")
|
||||
emit(" return a[0] < b[0]\n")
|
||||
emit("\n")
|
||||
emit("def addstringchar(a, b):\n")
|
||||
emit(" return a + b[0]\n")
|
||||
emit("\n")
|
||||
emit("def emit(string):\n")
|
||||
emit(" sys.stdout.write(string)\n")
|
||||
emit("\n")
|
||||
emit("def trace(header, value):\n")
|
||||
emit(" if os.environ.get('TRACE'):\n")
|
||||
emit(" sys.stderr.write(f'{header}={value!r}\\n')\n")
|
||||
emit("\n")
|
||||
emit("eof = chr(0)\n")
|
||||
emit("eol = chr(10)\n")
|
||||
emit("quote = chr(34)\n")
|
||||
emit("PEEK = None\n")
|
||||
emit("LINE = 1\n")
|
||||
emit("\n")
|
||||
emit("def peek():\n")
|
||||
emit(" global PEEK\n")
|
||||
emit(" if PEEK is None:\n")
|
||||
emit(" char = sys.stdin.read(1)\n")
|
||||
emit(" trace('char', char)\n")
|
||||
emit(" if not char:\n")
|
||||
emit(" PEEK = eof\n")
|
||||
emit(" else:\n")
|
||||
emit(" PEEK = char\n")
|
||||
emit(" return PEEK\n")
|
||||
emit("\n")
|
||||
emit("def skip():\n")
|
||||
emit(" global LINE\n")
|
||||
emit(" global PEEK\n")
|
||||
emit(" if eol == PEEK:\n")
|
||||
emit(" LINE += 1\n")
|
||||
emit(" PEEK = None\n")
|
||||
emit("\n")
|
||||
emit("def skipchar(char):\n")
|
||||
emit(" global LINE\n")
|
||||
emit(" assert char == peek(), (LINE, char, peek())\n")
|
||||
emit(" skip()\n")
|
||||
emit("\n")
|
||||
header = fileget("it0-in-header.py")
|
||||
emit(header)
|
||||
|
||||
def emitfooter():
|
||||
emit("if __name__ == '__main__':\n")
|
||||
emit(" main()\n")
|
||||
footer = fileget("it0-in-footer.py")
|
||||
emit(footer)
|
||||
|
||||
def main():
|
||||
emitheader()
|
||||
|
||||
2
it1-in-footer.py
Normal file
2
it1-in-footer.py
Normal file
@ -0,0 +1,2 @@
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
51
it1-in-header.py
Normal file
51
it1-in-header.py
Normal file
@ -0,0 +1,51 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
def eq(a, b):
|
||||
return a == b
|
||||
|
||||
def lt(a, b):
|
||||
return a[0] < b[0]
|
||||
|
||||
def addstringchar(a, b):
|
||||
return a + b[0]
|
||||
|
||||
def emit(string):
|
||||
sys.stdout.write(string)
|
||||
|
||||
def trace(header, value):
|
||||
if os.environ.get('TRACE'):
|
||||
sys.stderr.write(f'{header}={value!r}\\n')
|
||||
|
||||
eof = chr(0)
|
||||
eol = chr(10)
|
||||
quote = chr(34)
|
||||
PEEK = None
|
||||
LINE = 1
|
||||
|
||||
def peek():
|
||||
global PEEK
|
||||
if PEEK is None:
|
||||
char = sys.stdin.read(1)
|
||||
trace('char', char)
|
||||
if not char:
|
||||
PEEK = eof
|
||||
else:
|
||||
PEEK = char
|
||||
return PEEK
|
||||
|
||||
def skip():
|
||||
global LINE
|
||||
global PEEK
|
||||
if eol == PEEK:
|
||||
LINE += 1
|
||||
PEEK = None
|
||||
|
||||
def skipchar(char):
|
||||
global LINE
|
||||
assert char == peek(), (LINE, char, peek())
|
||||
skip()
|
||||
|
||||
def fileget(path):
|
||||
with open(f'./{path}', encoding='ASCII') as fil:
|
||||
return fil.read()
|
||||
54
it1-in.lang0
54
it1-in.lang0
@ -320,59 +320,13 @@ parsefunc:
|
||||
/
|
||||
|
||||
emitheader:
|
||||
emit "import os\n"
|
||||
emit "import sys\n"
|
||||
emit "\n"
|
||||
emit "def eq(a, b):\n"
|
||||
emit " return a == b\n"
|
||||
emit "\n"
|
||||
emit "def lt(a, b):\n"
|
||||
emit " return a[0] < b[0]\n"
|
||||
emit "\n"
|
||||
emit "def addstringchar(a, b):\n"
|
||||
emit " return a + b[0]\n"
|
||||
emit "\n"
|
||||
emit "def emit(string):\n"
|
||||
emit " sys.stdout.write(string)\n"
|
||||
emit "\n"
|
||||
emit "def trace(header, value):\n"
|
||||
emit " if os.environ.get('TRACE'):\n"
|
||||
emit " sys.stderr.write(f'{header}={value!r}\\n')\n"
|
||||
emit "\n"
|
||||
emit "eof = chr(0)\n"
|
||||
emit "eol = chr(10)\n"
|
||||
emit "quote = chr(34)\n"
|
||||
emit "PEEK = None\n"
|
||||
emit "LINE = 1\n"
|
||||
emit "\n"
|
||||
emit "def peek():\n"
|
||||
emit " global PEEK\n"
|
||||
emit " if PEEK is None:\n"
|
||||
emit " char = sys.stdin.read(1)\n"
|
||||
emit " trace('char', char)\n"
|
||||
emit " if not char:\n"
|
||||
emit " PEEK = eof\n"
|
||||
emit " else:\n"
|
||||
emit " PEEK = char\n"
|
||||
emit " return PEEK\n"
|
||||
emit "\n"
|
||||
emit "def skip():\n"
|
||||
emit " global LINE\n"
|
||||
emit " global PEEK\n"
|
||||
emit " if eol == PEEK:\n"
|
||||
emit " LINE += 1\n"
|
||||
emit " PEEK = None\n"
|
||||
emit "\n"
|
||||
emit "def skipchar(char):\n"
|
||||
emit " global LINE\n"
|
||||
emit " assert char == peek(), (LINE, char, peek())\n"
|
||||
emit " skip()\n"
|
||||
emit "\n"
|
||||
calc header fileget "it1-in-header.py"
|
||||
emit header
|
||||
/
|
||||
|
||||
emitfooter:
|
||||
emit "if __name__ == '__main__':\n"
|
||||
emit " main()\n"
|
||||
calc header fileget "it1-in-footer.py"
|
||||
emit header
|
||||
/
|
||||
|
||||
main:
|
||||
|
||||
136
it2-in-header.c
Normal file
136
it2-in-header.c
Normal file
@ -0,0 +1,136 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
char var_eof[2] = {-1, 0};
|
||||
char var_eol[2] = {10, 0};
|
||||
char var_quote[2] = {34, 0};
|
||||
char var_false[1] = {0};
|
||||
char var_true[2] = {'1', 0};
|
||||
|
||||
|
||||
char * eq(char * a, char * b)
|
||||
{
|
||||
return (strcmp(a, b) == 0) ? var_true : var_false;
|
||||
}
|
||||
|
||||
char * lt(char * a, char * b)
|
||||
{
|
||||
return (strcmp(a, b) < 0) ? var_true : var_false;
|
||||
}
|
||||
char * not(char * a)
|
||||
{
|
||||
return (strcmp(a, var_true) != 0) ? var_true : var_false;
|
||||
}
|
||||
|
||||
char * addstringchar(char * str, char * chr)
|
||||
{
|
||||
int str_len = strlen(str);
|
||||
assert(strlen(chr) == 1);
|
||||
char * res = malloc((str_len + 2) * sizeof(char));
|
||||
strcpy(res, str);
|
||||
res[str_len + 0] = chr[0];
|
||||
res[str_len + 1] = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
char * emit(char * str)
|
||||
{
|
||||
fputs(str, stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * trace(char * var_name, char * var_value)
|
||||
{
|
||||
const char * env_trace = getenv("TRACE");
|
||||
if( !env_trace ) return 0;
|
||||
fputs(var_name, stderr);
|
||||
fputs("=", stderr);
|
||||
fputs(var_value, stderr);
|
||||
fputs(var_eol, stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LINE = 1;
|
||||
|
||||
char * peek()
|
||||
{
|
||||
char * res = malloc(2*sizeof(char));
|
||||
res[0] = getc(stdin);
|
||||
res[1] = 0;
|
||||
ungetc(res[0], stdin);
|
||||
return res;
|
||||
}
|
||||
|
||||
void skip()
|
||||
{
|
||||
char c = getc(stdin);
|
||||
if( c == 10 ) LINE += 1;
|
||||
}
|
||||
|
||||
void skipchar(char * chr)
|
||||
{
|
||||
assert(strlen(chr) == 1);
|
||||
char * act = peek();
|
||||
assert(strlen(act) == 1);
|
||||
if( chr[0] == act[0] ) {skip(); return;};
|
||||
fprintf(stderr, "Expected '%c' on line %d but saw '%c' instead\n", chr[0], LINE, act[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char * fileget(char * var_path)
|
||||
{
|
||||
FILE * file_ptr;
|
||||
int file_size;
|
||||
char * res;
|
||||
|
||||
file_ptr = fopen(var_path, "r");
|
||||
if( NULL == file_ptr ) {
|
||||
fprintf(stderr, "Could not load file %s", var_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(file_ptr, 0, SEEK_END);
|
||||
file_size = ftell(file_ptr);
|
||||
fseek(file_ptr, 0, SEEK_SET);
|
||||
|
||||
res = malloc(file_size * sizeof(char));
|
||||
fread(res, sizeof(char), file_size, file_ptr);
|
||||
|
||||
fclose(file_ptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
void mapclear(char * map_name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void mapsetkey(char * map_name, char * key, char * value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
char * mapgetkey(char * map_name, char * key)
|
||||
{
|
||||
return "0";
|
||||
}
|
||||
|
||||
char * intinc(char * a)
|
||||
{
|
||||
int len = strlen(a);
|
||||
int val;
|
||||
int read = sscanf(a, "%d", &val);
|
||||
if( len != read ) {
|
||||
return "1";
|
||||
}
|
||||
|
||||
val += 1;
|
||||
|
||||
char * res = malloc((len + 1) * sizeof(char));
|
||||
sprintf(res, "%d", val);
|
||||
|
||||
return res;
|
||||
}
|
||||
108
it2-in.lang0
108
it2-in.lang0
@ -290,6 +290,11 @@ parsestat indent:
|
||||
break
|
||||
/
|
||||
skip
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
@ -299,11 +304,6 @@ parsestat indent:
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
set first "0"
|
||||
/
|
||||
skipchar eol
|
||||
@ -402,105 +402,13 @@ parsefunc:
|
||||
/
|
||||
|
||||
emitheader:
|
||||
emit "#include <assert.h>\n"
|
||||
emit "#include <stdio.h>\n"
|
||||
emit "#include <stdlib.h>\n"
|
||||
emit "#include <string.h>\n"
|
||||
emit eol
|
||||
emit eol
|
||||
emit "char var_eof[2] = {-1, 0};\n"
|
||||
emit "char var_eol[2] = {10, 0};\n"
|
||||
emit "char var_quote[2] = {34, 0};\n"
|
||||
emit "char var_false[1] = {0};\n"
|
||||
emit "char var_true[2] = {'1', 0};\n"
|
||||
emit eol
|
||||
emit eol
|
||||
emit "char * eq(char * a, char * b)\n"
|
||||
emit "{\n"
|
||||
emit " return (strcmp(a, b) == 0) ? var_true : var_false;\n"
|
||||
emit "}\n"
|
||||
emit "\n"
|
||||
emit "char * lt(char * a, char * b)\n"
|
||||
emit "{\n"
|
||||
emit " return (strcmp(a, b) < 0) ? var_true : var_false;\n"
|
||||
emit "}\n"
|
||||
emit "char * not(char * a)\n"
|
||||
emit "{\n"
|
||||
emit " return (strcmp(a, var_true) != 0) ? var_true : var_false;\n"
|
||||
emit "}\n"
|
||||
emit "\n"
|
||||
emit "char * addstringchar(char * str, char * chr)\n"
|
||||
emit "{\n"
|
||||
emit " int str_len = strlen(str);\n"
|
||||
emit " assert(strlen(chr) == 1);\n"
|
||||
emit " char * res = malloc((str_len + 2) * sizeof(char));\n"
|
||||
emit " strcpy(res, str);\n"
|
||||
emit " res[str_len + 0] = chr[0];\n"
|
||||
emit " res[str_len + 1] = 0;\n"
|
||||
emit " return res;\n"
|
||||
emit "}\n"
|
||||
emit "\n"
|
||||
emit "char * emit(char * str)\n"
|
||||
emit "{\n"
|
||||
emit " fputs(str, stdout);\n"
|
||||
emit " return 0;\n"
|
||||
emit "}\n"
|
||||
emit "\n"
|
||||
emit "char * trace(char * var_name, char * var_value)\n"
|
||||
emit "{\n"
|
||||
emit " const char * env_trace = getenv("
|
||||
emit quote
|
||||
emit "TRACE"
|
||||
emit quote
|
||||
emit ");\n"
|
||||
emit " if( !env_trace ) return 0;\n"
|
||||
emit " fputs(var_name, stderr);\n"
|
||||
emit " fputs("
|
||||
emit quote
|
||||
emit "="
|
||||
emit quote
|
||||
emit ", stderr);\n"
|
||||
emit " fputs(var_value, stderr);\n"
|
||||
emit " fputs(var_eol, stderr);\n"
|
||||
emit " return 0;\n"
|
||||
emit "}\n"
|
||||
emit eol
|
||||
emit "int LINE = 1;\n"
|
||||
emit eol
|
||||
emit "char * peek()\n"
|
||||
emit "{\n"
|
||||
emit " char * res = malloc(2*sizeof(char));\n"
|
||||
emit " res[0] = getc(stdin);\n"
|
||||
emit " res[1] = 0;\n"
|
||||
emit " ungetc(res[0], stdin);\n"
|
||||
emit " return res;\n"
|
||||
emit "}\n"
|
||||
emit "\n"
|
||||
emit "void skip()\n"
|
||||
emit "{\n"
|
||||
emit " char c = getc(stdin);\n"
|
||||
emit " if( c == 10 ) LINE += 1;\n"
|
||||
emit "}\n"
|
||||
emit "\n"
|
||||
emit "void skipchar(char * chr)\n"
|
||||
emit "{\n"
|
||||
emit " assert(strlen(chr) == 1);\n"
|
||||
emit " char * act = peek();\n"
|
||||
emit " assert(strlen(act) == 1);\n"
|
||||
emit " if( chr[0] == act[0] ) {skip(); return;};\n"
|
||||
emit " fprintf(stderr, "
|
||||
emit quote
|
||||
emit "Expected '%c' on line %d but saw '%c' instead%c"
|
||||
emit quote
|
||||
emit ", chr[0], LINE, act[0], 10);\n"
|
||||
emit " exit(1);\n"
|
||||
emit "}\n"
|
||||
emit "\n"
|
||||
declare header
|
||||
calc header fileget "it2-in-header.c"
|
||||
emit header
|
||||
return
|
||||
/
|
||||
|
||||
emitfooter:
|
||||
emit ""
|
||||
return
|
||||
/
|
||||
|
||||
|
||||
472
it3-in.lang0
Normal file
472
it3-in.lang0
Normal file
@ -0,0 +1,472 @@
|
||||
increaseindent indent:
|
||||
calc indent addstringchar indent " "
|
||||
calc indent addstringchar indent " "
|
||||
calc indent addstringchar indent " "
|
||||
calc indent addstringchar indent " "
|
||||
return indent
|
||||
/
|
||||
|
||||
lexident:
|
||||
declare char
|
||||
declare isbeforea
|
||||
declare isafterz
|
||||
declare word
|
||||
set word ""
|
||||
forever
|
||||
calc char peek
|
||||
calc isbeforea lt char "a"
|
||||
if isbeforea
|
||||
break
|
||||
/
|
||||
calc isafterz lt "z" char
|
||||
if isafterz
|
||||
break
|
||||
/
|
||||
calc word addstringchar word char
|
||||
skip
|
||||
/
|
||||
return word
|
||||
/
|
||||
|
||||
parseconststring:
|
||||
declare char
|
||||
declare iseof
|
||||
declare isquote
|
||||
skipchar quote
|
||||
forever
|
||||
calc char peek
|
||||
calc iseof eq char eof
|
||||
if iseof
|
||||
break
|
||||
/
|
||||
calc isquote eq char quote
|
||||
if isquote
|
||||
break
|
||||
/
|
||||
skip
|
||||
/
|
||||
skipchar quote
|
||||
emit "i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0)"
|
||||
return
|
||||
/
|
||||
|
||||
parseexprvarref:
|
||||
declare varname
|
||||
calc varname lexident
|
||||
emit "i8* %"
|
||||
emit varname
|
||||
return
|
||||
/
|
||||
|
||||
parseexprcall:
|
||||
declare char
|
||||
declare first
|
||||
declare funcname
|
||||
declare isspace
|
||||
declare isnotspace
|
||||
declare isfirst
|
||||
declare isnotfirst
|
||||
declare isquote
|
||||
declare isnotquote
|
||||
calc funcname lexident
|
||||
emit funcname
|
||||
emit "("
|
||||
set first "1"
|
||||
forever
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isnotspace
|
||||
break
|
||||
/
|
||||
skip
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
set first "0"
|
||||
/
|
||||
emit ")"
|
||||
return
|
||||
/
|
||||
|
||||
parsestatdeclare indent:
|
||||
declare var
|
||||
skipchar " "
|
||||
calc var lexident
|
||||
emit indent
|
||||
emit "char * var_"
|
||||
emit var
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestatset indent:
|
||||
declare var
|
||||
skipchar " "
|
||||
calc var lexident
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "var_"
|
||||
emit var
|
||||
emit " = "
|
||||
parseconststring
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestatcalc indent:
|
||||
declare var
|
||||
declare varidx
|
||||
skipchar " "
|
||||
calc var lexident
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "%"
|
||||
emit var
|
||||
calc varidx mapgetkey "funcvarused" var
|
||||
calc varidx intinc varidx
|
||||
mapsetkey "funcvarused" var varidx
|
||||
emit "."
|
||||
emit varidx
|
||||
emit " = call i8* @"
|
||||
parseexprcall
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parseblock indent/
|
||||
|
||||
parsestatif indent:
|
||||
declare indentt
|
||||
skipchar " "
|
||||
emit indent
|
||||
emit "if ( 0 < strlen("
|
||||
parseexprvarref
|
||||
emit ") )\n"
|
||||
emit indent
|
||||
emit "{\n"
|
||||
skipchar eol
|
||||
calc indentt increaseindent indent
|
||||
parseblock indentt
|
||||
emit indent
|
||||
emit "}\n"
|
||||
return
|
||||
/
|
||||
|
||||
parsestatforever indent:
|
||||
declare indentt
|
||||
emit indent
|
||||
emit "while (1)\n"
|
||||
emit indent
|
||||
emit "{\n"
|
||||
skipchar eol
|
||||
calc indentt increaseindent indent
|
||||
parseblock indentt
|
||||
emit indent
|
||||
emit "}\n"
|
||||
return
|
||||
/
|
||||
|
||||
parsestatbreak indent:
|
||||
emit indent
|
||||
emit "break;\n"
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestatreturn indent:
|
||||
declare char
|
||||
declare isspace
|
||||
declare isnotspace
|
||||
emit indent
|
||||
emit "ret "
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isspace
|
||||
skip
|
||||
parseexprvarref
|
||||
/
|
||||
if isnotspace
|
||||
emit "i18* 0"
|
||||
/
|
||||
emit ";"
|
||||
emit eol
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestattrace indent:
|
||||
declare varname
|
||||
emit indent
|
||||
emit "trace("
|
||||
emit quote
|
||||
skipchar " "
|
||||
calc varname lexident
|
||||
emit varname
|
||||
emit quote
|
||||
emit ", var_"
|
||||
emit varname
|
||||
emit ");\n"
|
||||
skipchar eol
|
||||
return
|
||||
/
|
||||
|
||||
parsestat indent:
|
||||
declare call
|
||||
declare char
|
||||
declare first
|
||||
declare iscall
|
||||
declare isfirst
|
||||
declare isspace
|
||||
declare isquote
|
||||
declare isnotfirst
|
||||
declare isnotspace
|
||||
declare isnotquote
|
||||
calc call lexident
|
||||
trace call
|
||||
calc iscall eq call "declare"
|
||||
if iscall
|
||||
parsestatdeclare indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "set"
|
||||
if iscall
|
||||
parsestatset indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "calc"
|
||||
if iscall
|
||||
parsestatcalc indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "if"
|
||||
if iscall
|
||||
parsestatif indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "forever"
|
||||
if iscall
|
||||
parsestatforever indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "break"
|
||||
if iscall
|
||||
parsestatbreak indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "return"
|
||||
if iscall
|
||||
parsestatreturn indent
|
||||
return
|
||||
/
|
||||
calc iscall eq call "trace"
|
||||
if iscall
|
||||
parsestattrace indent
|
||||
return
|
||||
/
|
||||
emit indent
|
||||
emit call
|
||||
emit "("
|
||||
set first "1"
|
||||
forever
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isnotspace
|
||||
break
|
||||
/
|
||||
skip
|
||||
calc char peek
|
||||
calc isquote eq char quote
|
||||
calc isnotquote not isquote
|
||||
if isquote
|
||||
parseconststring
|
||||
/
|
||||
if isnotquote
|
||||
parseexprvarref
|
||||
/
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
set first "0"
|
||||
/
|
||||
skipchar eol
|
||||
emit ");\n"
|
||||
return
|
||||
/
|
||||
|
||||
parseblock indent:
|
||||
declare char
|
||||
declare copy
|
||||
declare iseol
|
||||
declare isnoteol
|
||||
declare isdone
|
||||
declare iseoblock
|
||||
forever
|
||||
forever
|
||||
calc char peek
|
||||
calc iseol eq char eol
|
||||
calc isnoteol not iseol
|
||||
if isnoteol
|
||||
break
|
||||
/
|
||||
skip
|
||||
/
|
||||
set copy " "
|
||||
forever
|
||||
calc isdone eq copy indent
|
||||
if isdone
|
||||
break
|
||||
/
|
||||
skipchar "\t"
|
||||
calc copy increaseindent copy
|
||||
/
|
||||
calc char peek
|
||||
calc iseoblock eq char "/"
|
||||
if iseoblock
|
||||
skip
|
||||
skipchar eol
|
||||
break
|
||||
/
|
||||
skipchar "\t"
|
||||
parsestat indent
|
||||
/
|
||||
return
|
||||
/
|
||||
|
||||
parsefunc:
|
||||
declare char
|
||||
declare first
|
||||
declare funcname
|
||||
declare iseoblock
|
||||
declare isfirst
|
||||
declare isspace
|
||||
declare isnotfirst
|
||||
declare isnotspace
|
||||
declare var
|
||||
mapclear "funcvarused"
|
||||
calc funcname lexident
|
||||
trace funcname
|
||||
emit "define i8* @"
|
||||
emit funcname
|
||||
emit "("
|
||||
set first "1"
|
||||
forever
|
||||
calc char peek
|
||||
calc isspace eq char " "
|
||||
calc isnotspace not isspace
|
||||
if isnotspace
|
||||
break
|
||||
/
|
||||
skip
|
||||
calc var lexident
|
||||
calc isfirst eq first "1"
|
||||
calc isnotfirst not isfirst
|
||||
if isnotfirst
|
||||
emit ", "
|
||||
/
|
||||
emit "i8* %"
|
||||
emit var
|
||||
mapsetkey "funcvarused" "var" "0"
|
||||
emit "_0"
|
||||
set first "0"
|
||||
/
|
||||
calc char peek
|
||||
calc iseoblock eq char "/"
|
||||
if iseoblock
|
||||
skipchar "/"
|
||||
skipchar eol
|
||||
emit ");"
|
||||
emit "\n"
|
||||
return
|
||||
/
|
||||
skipchar ":"
|
||||
skipchar eol
|
||||
emit ")\n{\n"
|
||||
parseblock " "
|
||||
emit "}\n\n"
|
||||
return
|
||||
/
|
||||
|
||||
emitheader:
|
||||
emit "target datalayout = "
|
||||
emit quote
|
||||
emit "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
emit quote
|
||||
emit eol
|
||||
|
||||
emit "target triple = "
|
||||
emit quote
|
||||
emit "x86_64-pc-linux-gnu"
|
||||
emit quote
|
||||
emit eol
|
||||
|
||||
emit eol
|
||||
|
||||
emit "define i8* @addstringchar(i8* %0, i8* %1)"
|
||||
emit eol
|
||||
emit "{"
|
||||
emit eol
|
||||
emit " ; todo"
|
||||
emit eol
|
||||
emit " ret i8* %0;"
|
||||
emit eol
|
||||
emit "}"
|
||||
emit eol
|
||||
|
||||
emit eol
|
||||
|
||||
return
|
||||
/
|
||||
|
||||
emitfooter:
|
||||
emit ""
|
||||
return
|
||||
/
|
||||
|
||||
main:
|
||||
declare char
|
||||
declare iseof
|
||||
declare iseol
|
||||
declare isnoteol
|
||||
emitheader
|
||||
forever
|
||||
calc char peek
|
||||
calc iseof eq char eof
|
||||
if iseof
|
||||
break
|
||||
/
|
||||
forever
|
||||
calc char peek
|
||||
calc iseol eq char eol
|
||||
calc isnoteol not iseol
|
||||
if isnoteol
|
||||
break
|
||||
/
|
||||
skip
|
||||
/
|
||||
parsefunc
|
||||
/
|
||||
emitfooter
|
||||
return
|
||||
/
|
||||
19
notes.ll
Normal file
19
notes.ll
Normal file
@ -0,0 +1,19 @@
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-linux-gnu"
|
||||
|
||||
define i8* @addstringchar(i8* %0, i8* %1)
|
||||
{
|
||||
; todo
|
||||
ret i8* %0;
|
||||
}
|
||||
|
||||
define i8* @increaseindent(i8* %indent)
|
||||
{
|
||||
%indent.1 = call i8* @addstringchar(i8* %indent, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
%indent.2 = call i8* @addstringchar(i8* %indent.1, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
%indent.3 = call i8* @addstringchar(i8* %indent.2, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
%indent.4 = call i8* @addstringchar(i8* %indent.3, i8* noundef getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0));
|
||||
ret i8* %indent.4;
|
||||
}
|
||||
|
||||
@.str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1
|
||||
Loading…
x
Reference in New Issue
Block a user