about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen.pry21
-rw-r--r--src/llvm.pry2
-rw-r--r--src/parser.pry208
-rw-r--r--src/tokenizer.pry16
4 files changed, 155 insertions, 92 deletions
diff --git a/src/codegen.pry b/src/codegen.pry
index cb054ec..4c257b8 100644
--- a/src/codegen.pry
+++ b/src/codegen.pry
@@ -722,6 +722,27 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		return codegen_create_variable(c, v);
 	};
 	
+	if ((*expression).type == NODE_LOGICAL_EXPRESSION) {
+		let exp = (*(cast(*NODE_LOGICAL_EXPRESSION_DATA, (*expression).data)));
+		let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null));
+		assert(lhs_value != cast(*Variable, null));
+		let rhs_value = codegen_generate_expression_value(c, exp.rhs, cast(*i8, null));
+		assert(rhs_value != cast(*Variable, null));
+		
+		assert(compare_types(c, (*lhs_value).node_type, (*rhs_value).node_type, false));
+
+		let result = cast(LLVMValueRef, null);
+		if exp.an {
+			result = LLVMBuildAnd((*c).builder, (*lhs_value).value, (*rhs_value).value, "");
+		};
+		if !exp.an {
+			result = LLVMBuildOr((*c).builder, (*lhs_value).value, (*rhs_value).value, "");
+		};
+		assert(result != cast(LLVMValueRef, null));
+
+		return codegen_generate_literal(c, result, name, expression, (*lhs_value).node_type);
+	};
+	
 	if ((*expression).type == NODE_EQUALITY_EXPRESSION) {
 		let exp = (*(cast(*NODE_EQUALITY_EXPRESSION_DATA, (*expression).data)));
 		let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null));
diff --git a/src/llvm.pry b/src/llvm.pry
index 2feb815..6608372 100644
--- a/src/llvm.pry
+++ b/src/llvm.pry
@@ -329,6 +329,8 @@ extern LLVMBuildAdd = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMV
 extern LLVMBuildMul = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
 extern LLVMBuildSDiv = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
 extern LLVMBuildSRem = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+extern LLVMBuildAnd = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+extern LLVMBuildOr = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
 
 extern LLVMBuildGEP2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *LLVMValueRef, i64, *i8) => LLVMValueRef;
 extern LLVMAddGlobal = (LLVMModuleRef, LLVMTypeRef, *i8) => LLVMValueRef;
diff --git a/src/parser.pry b/src/parser.pry
index 0b448d0..1e7ff56 100644
--- a/src/parser.pry
+++ b/src/parser.pry
@@ -31,6 +31,7 @@ let NODE_IMPORT_DECLARATION = 4;
 let NODE_FUNCTION_CALL_STATEMENT = 5;
 let NODE_IF_STATEMENT = 6;
 let NODE_WHILE_STATEMENT = 7;
+let NODE_LOGICAL_EXPRESSION = 31;
 let NODE_EQUALITY_EXPRESSION = 8;
 let NODE_ADDITIVE_EXPRESSION = 9;
 let NODE_MULTIPLICATIVE_EXPRESSION = 10;
@@ -109,6 +110,12 @@ let NODE_WHILE_STATEMENT_DATA = struct {
     statements_len: i64,
 };
 
+let NODE_LOGICAL_EXPRESSION_DATA = struct {
+    lhs: *Node,
+    rhs: *Node,
+    an: bool,
+};
+
 let NODE_EQUALITY_EXPRESSION_DATA = struct {
     lhs: *Node,
     rhs: *Node,
@@ -897,107 +904,107 @@ let parser_parse_primary_expression = (p: *parser) => *Node {
 	return cast(*Node, null);
 };
 
-/* EqualityExpression ::= AdditiveExpression ("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression */
+/* EqualityExpression ::= AdditiveExpression (("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression)* */
 let parser_parse_equality_expression = (p: *parser) => *Node {
 	let lhs = parser_parse_additive_expression(p);
 	if lhs == cast(*Node, null) {
 	    return cast(*Node, null);
 	};	
 
-	let typ = -1;
-	let ex = parser_accept_parse(p, (ip: *parser) => *Node {
-		if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
-			return cast(*Node, null);
-		};
-		if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
-			return cast(*Node, null);
-		};
-		let n = Node{};
-		return create_node(ip, n);
-	});
-	if ex != cast(*Node, null) {
-		typ = EQUALITY_EXPRESSION_TYPE_EQ;
-	};
-
-	if (typ == -1) {
-		ex = parser_accept_parse(p, (ip: *parser) => *Node {
-			if (parser_accept_token(ip, TOKEN_BANG) == cast(*token, null)) {
+	while true {
+		let typ = -1;
+		let ex = parser_accept_parse(p, (ip: *parser) => *Node {
+			if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
 				return cast(*Node, null);
 			};
-			if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+			if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
 				return cast(*Node, null);
 			};
 			let n = Node{};
 			return create_node(ip, n);
 		});
-		if (ex != cast(*Node, null)) {
-			typ = EQUALITY_EXPRESSION_TYPE_NE;
+		if ex != cast(*Node, null) {
+			typ = EQUALITY_EXPRESSION_TYPE_EQ;
 		};
-	};
 
-	if (typ == -1) {
-		ex = parser_accept_parse(p, (ip: *parser) => *Node {
-			if (parser_accept_token(ip, TOKEN_LESS) == cast(*token, null)) {
-				return cast(*Node, null);
-			};
-			if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
-				return cast(*Node, null);
+		if (typ == -1) {
+			ex = parser_accept_parse(p, (ip: *parser) => *Node {
+				if (parser_accept_token(ip, TOKEN_BANG) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				let n = Node{};
+				return create_node(ip, n);
+			});
+			if (ex != cast(*Node, null)) {
+				typ = EQUALITY_EXPRESSION_TYPE_NE;
 			};
-			let n = Node{};
-			return create_node(ip, n);
-		});
-		if (ex != cast(*Node, null)) {
-			typ = EQUALITY_EXPRESSION_TYPE_LE;
 		};
-	};
 
-	if (typ == -1) {
-		ex = parser_accept_parse(p, (ip: *parser) => *Node {
-			if (parser_accept_token(ip, TOKEN_GREATER) == cast(*token, null)) {
-				return cast(*Node, null);
+		if (typ == -1) {
+			ex = parser_accept_parse(p, (ip: *parser) => *Node {
+				if (parser_accept_token(ip, TOKEN_LESS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				let n = Node{};
+				return create_node(ip, n);
+			});
+			if (ex != cast(*Node, null)) {
+				typ = EQUALITY_EXPRESSION_TYPE_LE;
 			};
-			if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
-				return cast(*Node, null);
+		};
+
+		if (typ == -1) {
+			ex = parser_accept_parse(p, (ip: *parser) => *Node {
+				if (parser_accept_token(ip, TOKEN_GREATER) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				let n = Node{};
+				return create_node(ip, n);
+			});
+			if (ex != cast(*Node, null)) {
+				typ = EQUALITY_EXPRESSION_TYPE_GE;
 			};
-			let n = Node{};
-			return create_node(ip, n);
-		});
-		if (ex != cast(*Node, null)) {
-			typ = EQUALITY_EXPRESSION_TYPE_GE;
 		};
-	};
 
-	if (typ == -1) {
-		if (parser_accept_token(p, TOKEN_LESS) != cast(*token, null)) {
+		if (typ == -1 and parser_accept_token(p, TOKEN_LESS) != cast(*token, null)) {
 			typ = EQUALITY_EXPRESSION_TYPE_LT;
 		};
-	};
 
-	if (typ == -1) {
-		if (parser_accept_token(p, TOKEN_GREATER) != cast(*token, null)) {
+		if (typ == -1 and parser_accept_token(p, TOKEN_GREATER) != cast(*token, null)) {
 			typ = EQUALITY_EXPRESSION_TYPE_GT;
 		};
-	};
 
-	if typ == -1 {
-		return cast(*Node, null);
-	};
-	
-	let rhs = parser_parse_additive_expression(p);
-	if rhs == cast(*Node, null) {
-	    return cast(*Node, null);
-	};	
-	
-	let d = cast(*NODE_EQUALITY_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_EQUALITY_EXPRESSION_DATA)));
-	(*d).lhs = lhs;
-	(*d).rhs = rhs;
-	(*d).typ = typ;
+		if typ == -1 {
+			break;
+		};
+		
+		let rhs = parser_parse_additive_expression(p);
+		if rhs == cast(*Node, null) {
+		    return cast(*Node, null);
+		};	
+		
+		let d = cast(*NODE_EQUALITY_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_EQUALITY_EXPRESSION_DATA)));
+		(*d).lhs = lhs;
+		(*d).rhs = rhs;
+		(*d).typ = typ;
 
-	let n = Node{};
-	n.type = NODE_EQUALITY_EXPRESSION ;
-	n.data = cast(*void, d);
+		let n = Node{};
+		n.type = NODE_EQUALITY_EXPRESSION ;
+		n.data = cast(*void, d);
 
-	return create_node(p, n); 
+		lhs = create_node(p, n);
+	};
+
+	return lhs; 
 };
 
 /* PostfixExpression ::= PrimaryExpression (CastStatement | SizeOfStatement | FunctionCallStatement | FieldAccess )* */
@@ -1027,15 +1034,11 @@ let parser_parse_unary_expression = (p: *parser) => *Node {
 	if parser_accept_token(p, TOKEN_BANG) != cast(*token, null) {
 	    typ = UNARY_EXPRESSION_TYPE_NOT;
 	};
-	if typ == -1 {
-		if parser_accept_token(p, TOKEN_MINUS) != cast(*token, null) {
-		    typ = UNARY_EXPRESSION_TYPE_MINUS;
-		};
+	if typ == -1 and parser_accept_token(p, TOKEN_MINUS) != cast(*token, null) {
+	    typ = UNARY_EXPRESSION_TYPE_MINUS;
 	};
-	if typ == -1 {
-		if parser_accept_token(p, TOKEN_MUL) != cast(*token, null) {
-		    typ = UNARY_EXPRESSION_TYPE_STAR;
-		};
+	if typ == -1 and parser_accept_token(p, TOKEN_MUL) != cast(*token, null) {
+	    typ = UNARY_EXPRESSION_TYPE_STAR;
 	};
 	if typ == -1 {
 		return parser_parse_postfix_expression(p);
@@ -1104,10 +1107,8 @@ let parser_parse_additive_expression = (p: *parser) => *Node {
 		let plus = parser_accept_token(p, TOKEN_PLUS);
 		let minus = parser_accept_token(p, TOKEN_MINUS);
 
-		if plus == cast(*token, null) {
-			if minus == cast(*token, null) {
-				break;
-			};
+		if plus == cast(*token, null) and minus == cast(*token, null) {
+			break;
 		};
 
 		let rhs = parser_parse_multiplicative_expression(p);
@@ -1127,18 +1128,41 @@ let parser_parse_additive_expression = (p: *parser) => *Node {
 	return lhs;
 };
 
-/* Expression ::= EqualityExpression | AdditiveExpression */
-let parser_parse_expression = (p: *parser) => *Node {
-	let ex = parser_accept_parse(p, parser_parse_equality_expression);
-	if ex != cast(*Node, null) {
-		return ex;
+/* LogicalExpression ::= EqualityExpression (("and" | "or") EqualityExpression)* */
+let parser_parse_logical_expression = (p: *parser) => *Node {
+	let lhs = parser_parse_equality_expression(p);
+	if lhs == cast(*Node, null) {
+		return cast(*Node, null);
 	};
-	let ax = parser_accept_parse(p, parser_parse_additive_expression);
-	if ax != cast(*Node, null) {
-		return ax;
+
+	while true {
+		let an = parser_accept_token(p, TOKEN_AND);
+		let o = parser_accept_token(p, TOKEN_OR);
+
+		if an == cast(*token, null) and o == cast(*token, null) {
+			break;
+		};
+
+		let rhs = parser_parse_equality_expression(p);
+		if rhs == cast(*Node, null) {
+			return cast(*Node, null);
+		};
+
+		let new_lhs_data = cast(*NODE_LOGICAL_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_LOGICAL_EXPRESSION_DATA)));
+		((*new_lhs_data).an) = an != cast(*token, null);
+		((*new_lhs_data).lhs) = lhs;
+		((*new_lhs_data).rhs) = rhs;
+		let new_lhs = Node{};
+		new_lhs.type = NODE_LOGICAL_EXPRESSION;
+		new_lhs.data = cast(*void, new_lhs_data);
+		lhs = create_node(p, new_lhs);
 	};
+	return lhs;
+};
 
-	return cast(*Node, null);
+/* Expression ::= LogicalExpression */
+let parser_parse_expression = (p: *parser) => *Node {
+	return parser_parse_logical_expression(p);
 };
 
 /* AssignmentStatement ::= ("let")? ("*")? Expression EQUALS Expression */
diff --git a/src/tokenizer.pry b/src/tokenizer.pry
index ddc2cef..c809420 100644
--- a/src/tokenizer.pry
+++ b/src/tokenizer.pry
@@ -18,6 +18,8 @@ let TOKEN_CONTINUE   = 8;
 let TOKEN_ARROW      = 9;
 let TOKEN_STRUCT     = 10;
 let TOKEN_TYPE       = 34;
+let TOKEN_AND        = 35;
+let TOKEN_OR         = 36;
 
 /* Identifiers */
 let TOKEN_IDENTIFIER = 11;
@@ -101,6 +103,12 @@ let print_tokens = (ts: *token, ts_len: i64) => i64 {
 		if (to.type == TOKEN_TYPE) {
 			printf("Type\n");
 		};
+		if (to.type == TOKEN_AND) {
+			printf("And\n");
+		};
+		if (to.type == TOKEN_OR) {
+			printf("Or\n");
+		};
 		if (to.type == TOKEN_IDENTIFIER) {
 			printf("Identifier: %s\n", cast(*i8, to.data));
 		};
@@ -398,6 +406,14 @@ let tokenizer_next = (t: *tokenizer) => *token {
 	    (*to).type = TOKEN_TYPE;
 	    return to;
 	};
+	if tokenizer_accept_string(t, "and") {
+	    (*to).type = TOKEN_AND;
+	    return to;
+	};
+	if tokenizer_accept_string(t, "or") {
+	    (*to).type = TOKEN_OR;
+	    return to;
+	};
 
 	if tokenizer_accept_string(t, "=>") {
 	    (*to).type = TOKEN_ARROW;