diff --git a/examples/hello.ry b/examples/hello.ry index f3909eb..fc0e890 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -36,11 +36,14 @@ fn func_refer_param(b: i32) i32 { } fn multwo(num: i32, double_flag: bool) i32 { + if (!double_flag) { + var value = 32; + return value; + } + if (double_flag) { - var truthy = true; return num * 2; } else { - var falsey = false; return num; } } diff --git a/src/analysis.zig b/src/analysis.zig index 8a6a90d..acb9b6d 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -214,9 +214,9 @@ pub const TypeSolver = struct { }; }, - // for now, unary operators only have .Not .Unary => |unary| { var right_type = try self.resolveExprType(ctx, unary.right); + return switch (unary.op) { .Negate => right_type, .Not => right_type, diff --git a/src/ast.zig b/src/ast.zig index efb0015..85eb602 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -29,7 +29,6 @@ pub const ParamDecl = struct { pub const MethodData = struct { variable: Token, typ: Token, - mutable: bool, }; pub const FnDecl = struct { @@ -288,10 +287,6 @@ pub const FieldList = std.ArrayList(StructField); pub const StructField = struct { name: Token, typ: Token, - - mutable: bool = false, - public: bool = false, - mutable_outside: bool = false, }; pub const Struct = struct { diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 13b6fe4..ad6ec20 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -48,11 +48,7 @@ pub fn printNode(node: *const Node, ident: usize) void { const vari = method.variable.lexeme; const typ = method.typ.lexeme; - if (method.mutable) { - warn("(method mut {} {} {} {} (", vari, typ, name, ret_type); - } else { - warn("(method {} {} {} {} (", vari, typ, name, ret_type); - } + warn("(method {} {} {} {} (", vari, typ, name, ret_type); } else { warn("(fn {} {} (", name, ret_type); } @@ -112,22 +108,7 @@ pub fn printNode(node: *const Node, ident: usize) void { .Struct => |struc| { print(ident, "(struct {} (\n", struc.name.lexeme); for (struc.fields.toSlice()) |field| { - printIdent(ident + 1); - if (field.mutable) { - std.debug.warn("(mut "); - } else { - std.debug.warn("("); - } - - if (field.public) { - std.debug.warn("pub "); - } - - if (field.mutable_outside) { - std.debug.warn("MUT_OUT "); - } - - std.debug.warn("{} {})\n", field.name.lexeme, field.typ.lexeme); + print(ident + 1, "({} {})\n", field.name.lexeme, field.typ.lexeme); } print(ident, "))\n"); }, diff --git a/src/codegen.zig b/src/codegen.zig index e71517e..592a79b 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -132,6 +132,15 @@ pub const Codegen = struct { }; }, + .Unary => |unary| { + var right = try self.emitExpr(builder, unary.right); + + return switch (unary.op) { + .Negate => llvm.LLVMBuildNeg(builder, right, c"neg_tmp"), + .Not => llvm.LLVMBuildNot(builder, right, c"neg_tmp"), + }; + }, + .Binary => |binary| { var left = try self.emitExpr(builder, binary.left); var right = try self.emitExpr(builder, binary.right); diff --git a/src/parsers.zig b/src/parsers.zig index 026d11e..81c83cb 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -23,12 +23,6 @@ const Stmt = ast.Stmt; const TokenList = std.ArrayList(Token); -const FieldState = struct { - public: bool = false, - mutable: bool = false, - mutable_outside: bool = false, -}; - const operator_tokens = [_][]const u8{ "+", "-", "*", "/", "%", ">", ">=", "<", "<=", "==", }; @@ -511,19 +505,12 @@ pub const Parser = struct { ); } - /// parse the (v [mut] T) part of the method (defined here + /// parse the (v T) part of the method (defined here /// as a premethod) fn parsePreMethod(self: *@This()) !?*ast.MethodData { _ = try self.consumeSingle(.LeftParen); - var mutable_ref: bool = false; const variable = try self.consumeSingle(.Identifier); - - if (self.check(.Mut)) { - _ = try self.consumeSingle(.Mut); - mutable_ref = true; - } - const typ = try self.consumeSingle(.Identifier); _ = try self.consumeSingle(.RightParen); @@ -533,7 +520,6 @@ pub const Parser = struct { method.* = ast.MethodData{ .variable = variable, .typ = typ, - .mutable = mutable_ref, }; return method; @@ -581,27 +567,14 @@ pub const Parser = struct { _ = try self.consumeSingle(.LeftBrace); - var field_state = FieldState{}; - while (!self.check(.RightBrace)) { - try self.parseFieldModifiers(&field_state); - const field_name = try self.consumeSingle(.Identifier); self.setErrContext("struct {} field {}", name, field_name); const field_type = try self.consumeSingle(.Identifier); - - // we could create a FieldState on the heap and copy our current - // field state into a StructField.state, but copying via this makes - // things so much nicer. - try fields.append(ast.StructField{ .name = field_name, .typ = field_type, - - .mutable = field_state.mutable, - .public = field_state.public, - .mutable_outside = field_state.mutable_outside, }); } @@ -610,51 +583,6 @@ pub const Parser = struct { return Node.mkStructDecl(self.allocator, name, fields); } - fn parseFieldModifiers(self: *@This(), field_state: *FieldState) !void { - - // there are five access modifiers: - // - none (private immutable) - // - mut (private mutable) - // - pub (public immutable) - // - pub mut (public mutable only in module) - // - pub mut mut (public mutable everywhere) - - // this function takes care of that by changing the current FieldState - // to what the modifiers dictate. - switch (self.peek().typ) { - .Mut => { - // There are no oher modifiers that start with mut, so we - // can just go the way of marking it as mutable - _ = try self.consumeSingle(.Mut); - _ = try self.consumeSingle(.Colon); - - field_state.mutable = true; - }, - - // 'pub', 'pub mut', and 'pub mut mut' are all handled here - .Pub => { - _ = try self.consumeSingle(.Pub); - field_state.public = true; - - if (self.check(.Mut)) { - _ = try self.consumeSingle(.Mut); - - field_state.mutable = true; - if (self.check(.Mut)) { - _ = try self.consumeSingle(.Mut); - field_state.mutable_outside = true; - } - } - - _ = try self.consumeSingle(.Colon); - }, - - // if it isn't mut or pub we're likely in an identifier, just - // ignore it. - else => return, - } - } - fn parseEnumDecl(self: *@This()) !*Node { var fields = ast.TokenList.init(self.allocator); errdefer fields.deinit(); @@ -848,29 +776,22 @@ pub const Parser = struct { // there can be two assignments coming out of this function: // - an assignment to a variable with = // - an update to a variable with +=, -= - - // one is a statement, other is an expression. since the normal result - // of this is an Expr, we wrap variable assignments in an Expr as well. - var mutable: bool = false; - - if (self.check(.Mut)) { - _ = try self.consumeSingle(.Mut); - mutable = true; - } - var expr = try self.parseOr(); if (self.compareAnyOf(&[_]TokenType{ .Equal, .PlusEqual, .MinusEqual, .StarEqual, .SlashEqual, })) { - return try self.finishAssignment(expr, mutable); + return try self.finishAssignment(expr); } return expr; } - fn finishAssignment(self: *@This(), expr: *Expr, mutable: bool) !*Expr { + fn finishAssignment( + self: *@This(), + expr: *Expr, + ) !*Expr { var op_tok = self.peek(); _ = try self.nextToken(); @@ -1033,8 +954,9 @@ pub const Parser = struct { fn parseUnary(self: *@This()) anyerror!*Expr { if (self.compareAnyOf(&[_]TokenType{ .Bang, .Minus })) { - var op = self.previous(); - var right = try self.parseUnary(); + var op = self.peek(); + _ = try self.nextToken(); + var right = try self.parseCall(); return try self.mkUnary(try toUnaryOperator(op), right); }