Author: mesyeti <mesyeti@mesyeti.uk>
add some operators and start working on standard library
.gitignore | 3 +++ activate | 1 + basic-std/.gitignore | 3 +++ basic-std/Makefile | 15 +++++++++++++++ basic-std/compile_test.sh | 3 +++ basic-std/std/io.bas | 16 ++++++++++++++++ basic-std/test.bas | 10 ++++++++++ basic/source/frontend/c89.c | 20 +++++++++++--------- basic/source/lexer.c | 19 +++++++++++++++++++ basic/source/lexer.h | 4 +++- basic/source/parser.c | 21 +++++++++++++++++++-- basic/source/semanticAnalysis.c | 2 ++ build.sh | 22 ++++++++++++++++++++++
diff --git a/.gitignore b/.gitignore index c8bb3af90375901e32ccc9cc3b4d1e62420335b4..5a59bf258ff7d133d5db6c6d44fedb9a9fdafa23 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ # debug information files *.dwo + +# nitron stuff +/out/* diff --git a/activate b/activate new file mode 100644 index 0000000000000000000000000000000000000000..479e4ae6325860b529e550fcbdb906aa9a1a0ecc --- /dev/null +++ b/activate @@ -0,0 +1 @@ +export PATH="$(realpath out/bin):$PATH" diff --git a/basic/source/frontend/c89.c b/basic/source/frontend/c89.c index c9c894aecf0889005bd5c8f36e5b5c7dd51c67ec..7f31c59e4d8756607456a1a398d947edb0273c77 100644 --- a/basic/source/frontend/c89.c +++ b/basic/source/frontend/c89.c @@ -121,15 +121,16 @@ fprintf(out, "("); CompileExprNode(node->bin.left); switch (node->bin.op) { - case TOKEN_ADD: fprintf(out, "+"); break; - case TOKEN_SUBTRACT: fprintf(out, "-"); break; - case TOKEN_MULTIPLY: fprintf(out, "*"); break; - case TOKEN_DIVIDE: fprintf(out, "/"); break; - case TOKEN_MOD: fprintf(out, "%%"); break; - case TOKEN_EQUAL: fprintf(out, "=="); break; - case TOKEN_LESS: fprintf(out, "<"); break; - case TOKEN_GREATER: fprintf(out, ">"); break; - case TOKEN_ASSIGN: fprintf(out, "="); break; + case TOKEN_ADD: fprintf(out, "+"); break; + case TOKEN_SUBTRACT: fprintf(out, "-"); break; + case TOKEN_MULTIPLY: fprintf(out, "*"); break; + case TOKEN_DIVIDE: fprintf(out, "/"); break; + case TOKEN_MOD: fprintf(out, "%%"); break; + case TOKEN_EQUAL: fprintf(out, "=="); break; + case TOKEN_LESS: fprintf(out, "<"); break; + case TOKEN_GREATER: fprintf(out, ">"); break; + case TOKEN_ASSIGN: fprintf(out, "="); break; + case TOKEN_NOT_EQUAL: fprintf(out, "!="); break; case TOKEN_DOT: { UsedType type = SemanticAnalysis_NodeAsUsedType(node->bin.left); @@ -156,6 +157,7 @@ case TOKEN_ADD: fprintf(out, "+"); break; case TOKEN_SUBTRACT: fprintf(out, "-"); break; case TOKEN_ADDRESS: fprintf(out, "&"); break; case TOKEN_ACCESS: fprintf(out, "*"); break; + case TOKEN_NOT: fprintf(out, "!"); break; default: assert(0); } diff --git a/basic/source/lexer.c b/basic/source/lexer.c index 90404adda62e05457c7b27eae04ed267139b0c24..2f729de40820e9a1df853dc5ff5598c062812166 100644 --- a/basic/source/lexer.c +++ b/basic/source/lexer.c @@ -108,6 +108,23 @@ case '-': *token = TOKEN(TOKEN_SUBTRACT, NULL); return LEXER_TOKEN; case '*': *token = TOKEN(TOKEN_MULTIPLY, NULL); return LEXER_TOKEN; case '/': *token = TOKEN(TOKEN_DIVIDE, NULL); return LEXER_TOKEN; case '%': *token = TOKEN(TOKEN_MOD, NULL); return LEXER_TOKEN; + case '!': { + char next; + GET_CHAR(next); + + if (next == '=') { + *token = TOKEN(TOKEN_NOT_EQUAL, NULL); + } + else { + *token = TOKEN(TOKEN_NOT, NULL); + + if (next == '\n') { + -- lexer->line; + } + fseek(lexer->file, -1, SEEK_CUR); + } + return LEXER_TOKEN; + } case '=': { char next; GET_CHAR(next); @@ -233,6 +250,8 @@ case TOKEN_LESS: return "less"; case TOKEN_GREATER: return "greater"; case TOKEN_ADDRESS: return "address"; case TOKEN_ACCESS: return "access"; + case TOKEN_NOT: return "not"; + case TOKEN_NOT_EQUAL: return "not equal"; default: assert(0); } } diff --git a/basic/source/lexer.h b/basic/source/lexer.h index 48e11c8255f290178d8bf33d7a55184ce107b7bc..f83f268cf819277e0caf9781d9332cba025e9c6e 100644 --- a/basic/source/lexer.h +++ b/basic/source/lexer.h @@ -50,7 +50,9 @@ TOKEN_LESS, TOKEN_GREATER, TOKEN_ASSIGN, TOKEN_ADDRESS, - TOKEN_ACCESS + TOKEN_ACCESS, + TOKEN_NOT, + TOKEN_NOT_EQUAL } TokenType; enum { diff --git a/basic/source/parser.c b/basic/source/parser.c index 5e2a744114afdf6c5f07f22353260cca243f6632..2a585fc994f18509254620a874fd36f3069027f9 100644 --- a/basic/source/parser.c +++ b/basic/source/parser.c @@ -128,7 +128,8 @@ switch (tok->type) { case TOKEN_ADD: case TOKEN_SUBTRACT: case TOKEN_ADDRESS: - case TOKEN_ACCESS: return true; + case TOKEN_ACCESS: + case TOKEN_NOT: return true; default: return false; } } @@ -208,7 +209,8 @@ while ( (p->tokens[p->i].type == TOKEN_EQUAL) || (p->tokens[p->i].type == TOKEN_LESS) || - (p->tokens[p->i].type == TOKEN_GREATER) + (p->tokens[p->i].type == TOKEN_GREATER) || + (p->tokens[p->i].type == TOKEN_NOT_EQUAL) ) { TokenType op = p->tokens[p->i].type; Advance(p); @@ -658,6 +660,21 @@ Expect(p, TOKEN_IDENTIFIER); ret.name = NewString(p->tokens[p->i].contents); Advance(p); + + while (p->tokens[p->i].type != TOKEN_LINE) { + Expect(p, TOKEN_DOT); + Advance(p); + Expect(p, TOKEN_IDENTIFIER); + + // TODO: improve this + char* tmp = ConcatString(ret.name, "/"); + char* new = ConcatString(tmp, p->tokens[p->i].contents); + free(ret.name); + ret.name = new; + + Advance(p); + } + Expect(p, TOKEN_LINE); Node node; diff --git a/basic/source/semanticAnalysis.c b/basic/source/semanticAnalysis.c index 86d59ee8a3f4ac1c0555a6796bddfa5a330780b7..4f06c5c0abcf1332f55b78d69b6df72c7cfe7450 100644 --- a/basic/source/semanticAnalysis.c +++ b/basic/source/semanticAnalysis.c @@ -153,6 +153,7 @@ if (left.ptr) { if (right.ptr) { switch (node->bin.op) { case TOKEN_EQUAL: + case TOKEN_NOT_EQUAL: case TOKEN_LESS: case TOKEN_GREATER: return GET_PRIM("bool", 0); case TOKEN_SUB: return GET_PRIM("uint", 0); @@ -201,6 +202,7 @@ } } else if (!right.ptr) { switch (node->bin.op) { + case TOKEN_NOT_EQUAL: case TOKEN_EQUAL: return GET_PRIM("bool", 0); case TOKEN_LESS: case TOKEN_GREATER: { diff --git a/basic-std/.gitignore b/basic-std/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d44c303d48e197fbc52362e8aae1cc509a2d0986 --- /dev/null +++ b/basic-std/.gitignore @@ -0,0 +1,3 @@ +/libstd.a +/out +/bin diff --git a/basic-std/Makefile b/basic-std/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5eb68946d5d081ba2edffc0c064d161e117e2e02 --- /dev/null +++ b/basic-std/Makefile @@ -0,0 +1,15 @@ +SRC = $(wildcard std/*.bas) +OBJ = $(addsuffix .o,$(subst std/,bin/,$(basename $(SRC)))) +OUT = libstd.a + +compile: ./bin $(OBJ) $(SRC) + ar rcs $(OUT) $(OBJ) + +./bin: + mkdir -p bin + +bin/%.o: std/%.bas $(SRC) + nitron-basic --obj $< -o $@ + +clean: + rm bin/*.o $(OUT) diff --git a/basic-std/compile_test.sh b/basic-std/compile_test.sh new file mode 100755 index 0000000000000000000000000000000000000000..650b524b5ae25d8b9adbc7ea1c56d037a4fac893 --- /dev/null +++ b/basic-std/compile_test.sh @@ -0,0 +1,3 @@ +nitron-basic test.bas --obj -o test.o +gcc test.o libstd.a -o out +rm test.o.c test.o diff --git a/basic-std/std/io.bas b/basic-std/std/io.bas new file mode 100644 index 0000000000000000000000000000000000000000..d751ab166b51048099aac4aa4d4f16ed1730d633 --- /dev/null +++ b/basic-std/std/io.bas @@ -0,0 +1,16 @@ +extern func puts(str as ptr(char)) i32 +extern func putchar(ch as char) i32 + +sub PrintChar(ch as char) + putchar(ch) +end + +' TODO: PrintStr + +sub PrintStrLn(str as ptr(char)) + puts(str) +end + +sub NewLine() + puts("") +end diff --git a/basic-std/test.bas b/basic-std/test.bas new file mode 100644 index 0000000000000000000000000000000000000000..c8029f0ca77f171a8d37c52efcbe026bb3882d26 --- /dev/null +++ b/basic-std/test.bas @@ -0,0 +1,10 @@ +program test + +import std.io + +dim i as int + +while i != 10 do + PrintStrLn("Hello, world!") + i = i + 1 +end diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..b55966e84bb22281d9bfcc8f3b3d422c4054e352 --- /dev/null +++ b/build.sh @@ -0,0 +1,22 @@ +echo "Storing output in out/ folder" +if [ -e "out" ]; then + rm -r out +fi +mkdir out +mkdir out/bin +mkdir out/lib + +echo "==================" +echo "= BASIC Compiler =" +echo "==================" +cd basic +make + +if [ $? -ne 0 ]; then + echo "Compilation failed" + exit +fi +cd .. +mv basic/nitron-basic out/bin/ + +echo "Finished building nitron"