add lots of TODOs for variables and type analysis of statements
- comp_ctx: replace Function.symbols to Function.env
This commit is contained in:
parent
45275d73db
commit
bf035abadf
4 changed files with 75 additions and 8 deletions
|
@ -1,7 +1,9 @@
|
||||||
// import std;
|
const (
|
||||||
|
test_var = 1 + 3
|
||||||
|
)
|
||||||
|
|
||||||
fn f() i32 {
|
fn f() i32 {
|
||||||
var a = 2;
|
var a = 3;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,10 +11,6 @@ fn f2() i32 {
|
||||||
return f() + 2;
|
return f() + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
piss = 1 + 3
|
|
||||||
)
|
|
||||||
|
|
||||||
enum B {
|
enum B {
|
||||||
a
|
a
|
||||||
b
|
b
|
||||||
|
|
|
@ -192,6 +192,22 @@ pub const Codegen = struct {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// TODO finish this
|
||||||
|
.Assign => |assign| {
|
||||||
|
// TODO find assign.name on the "parent context", we should have
|
||||||
|
// a way to do name resolution that is completely relative to
|
||||||
|
// where we currently are, and go up in scope. so that we find
|
||||||
|
// the LLVMValueRef.
|
||||||
|
|
||||||
|
// we will also need to repeat the step for the type resolver
|
||||||
|
|
||||||
|
//var typ = self.findCurrent(assign.name);
|
||||||
|
var assign_expr = try self.emitExpr(builder, assign.value);
|
||||||
|
|
||||||
|
// TODO rm null
|
||||||
|
return llvm.LLVMBuildStore(builder, null, assign_expr);
|
||||||
|
},
|
||||||
|
|
||||||
else => {
|
else => {
|
||||||
std.debug.warn("Got unexpected expr {}\n", ast.ExprType(expr.*));
|
std.debug.warn("Got unexpected expr {}\n", ast.ExprType(expr.*));
|
||||||
return CompileError.EmitError;
|
return CompileError.EmitError;
|
||||||
|
@ -286,7 +302,7 @@ pub const Codegen = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
else => {
|
else => {
|
||||||
std.debug.warn("Got unexpected statement {}\n", stmt.*);
|
std.debug.warn("Got unexpected stmt {}\n", stmt.*);
|
||||||
return CompileError.EmitError;
|
return CompileError.EmitError;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,12 @@ pub const SymbolUnderlyingType = union(SymbolUnderlyingTypeEnum) {
|
||||||
Enum: []const u8,
|
Enum: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Scope = std.StringHashMap(SymbolUnderlyingType);
|
||||||
|
pub const Environment = struct {
|
||||||
|
parent: *Environment,
|
||||||
|
scope: Scope,
|
||||||
|
};
|
||||||
|
|
||||||
// functions, for our purposes, other than symbols, have:
|
// functions, for our purposes, other than symbols, have:
|
||||||
// - a return type
|
// - a return type
|
||||||
// - TODO parameters
|
// - TODO parameters
|
||||||
|
@ -39,7 +45,7 @@ pub const FunctionSymbol = struct {
|
||||||
/// Parameters for a function are also a table instead of an ArrayList
|
/// Parameters for a function are also a table instead of an ArrayList
|
||||||
/// because we want to resolve identifiers to them.
|
/// because we want to resolve identifiers to them.
|
||||||
parameters: UnderlyingTypeMap,
|
parameters: UnderlyingTypeMap,
|
||||||
symbols: SymbolTable,
|
env: *Environment,
|
||||||
|
|
||||||
/// Find a given identifier in the function. Can resolve to either a parameter
|
/// Find a given identifier in the function. Can resolve to either a parameter
|
||||||
pub fn findSymbol(self: *const @This(), identifier: []const u8) ?SymbolData {
|
pub fn findSymbol(self: *const @This(), identifier: []const u8) ?SymbolData {
|
||||||
|
|
|
@ -170,6 +170,45 @@ pub const TypeSolver = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn nodePass(
|
||||||
|
self: *@This(),
|
||||||
|
ctx: *comp.CompilationContext,
|
||||||
|
stmt: ast.Stmt,
|
||||||
|
) !void {
|
||||||
|
switch (stmt) {
|
||||||
|
|
||||||
|
// There are no side-effects to the type system when the statement
|
||||||
|
// is just an expression or a println. we just resolve it
|
||||||
|
// to ensure we dont have type errors.
|
||||||
|
.Expr => |expr_ptr| try self.resolveExprType(ctx, expr_ptr),
|
||||||
|
.Println => |expr_ptr| try self.resolveExprType(ctx, expr_ptr),
|
||||||
|
|
||||||
|
// VarDecl means we check the type of the expression and
|
||||||
|
// insert it into the context, however we need to know a pointer
|
||||||
|
// to where we are, scope-wise, we don't have that info here,
|
||||||
|
// so it should be implicit into the context.
|
||||||
|
.VarDecl => @panic("TODO vardecl"),
|
||||||
|
|
||||||
|
// If create two scopes for each branch of the if
|
||||||
|
.If => @panic("TODO ifstmt"),
|
||||||
|
|
||||||
|
// Loop (creates 1 scope) asserts that the expression
|
||||||
|
// type is a bool
|
||||||
|
.Loop => @panic("TODO loop"),
|
||||||
|
|
||||||
|
// For (creates 1 scope) receives arrays, which we dont have yet
|
||||||
|
.For => @panic("TODO for"),
|
||||||
|
|
||||||
|
// Returns dont cause any type system things as they deal with
|
||||||
|
// values, however, we must ensure that the expression type
|
||||||
|
// matches the function type (must fetch from context, or we could
|
||||||
|
// pull a hack with err contexts, lol)
|
||||||
|
.Return => @panic("TODO return"),
|
||||||
|
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn nodePass(
|
pub fn nodePass(
|
||||||
self: *@This(),
|
self: *@This(),
|
||||||
ctx: *comp.CompilationContext,
|
ctx: *comp.CompilationContext,
|
||||||
|
@ -194,6 +233,14 @@ pub const TypeSolver = struct {
|
||||||
try parameters.append(param_type.?);
|
try parameters.append(param_type.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO scopes: bump scope
|
||||||
|
|
||||||
|
for (decl.body.toSlice()) |stmt| {
|
||||||
|
try self.stmtPass(ctx, stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO scopes: down scope
|
||||||
|
|
||||||
// TODO symbols and scope resolution, that's
|
// TODO symbols and scope resolution, that's
|
||||||
// its own can of worms
|
// its own can of worms
|
||||||
var symbols = comp.SymbolTable.init(self.allocator);
|
var symbols = comp.SymbolTable.init(self.allocator);
|
||||||
|
|
Loading…
Reference in a new issue