nitron

commit fb650bcbff99940f0221a452db95f5d8a4c9b684

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"