add lots of TODOs for variables and type analysis of statements

- comp_ctx: replace Function.symbols to Function.env
This commit is contained in:
Luna 2019-09-26 00:11:48 -03:00
parent 45275d73db
commit bf035abadf
4 changed files with 75 additions and 8 deletions

View file

@ -1,7 +1,9 @@
// import std;
const (
test_var = 1 + 3
)
fn f() i32 {
var a = 2;
var a = 3;
return 2;
}
@ -9,10 +11,6 @@ fn f2() i32 {
return f() + 2;
}
const (
piss = 1 + 3
)
enum B {
a
b

View file

@ -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 => {
std.debug.warn("Got unexpected expr {}\n", ast.ExprType(expr.*));
return CompileError.EmitError;
@ -286,7 +302,7 @@ pub const Codegen = struct {
},
else => {
std.debug.warn("Got unexpected statement {}\n", stmt.*);
std.debug.warn("Got unexpected stmt {}\n", stmt.*);
return CompileError.EmitError;
},
}

View file

@ -29,6 +29,12 @@ pub const SymbolUnderlyingType = union(SymbolUnderlyingTypeEnum) {
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:
// - a return type
// - TODO parameters
@ -39,7 +45,7 @@ pub const FunctionSymbol = struct {
/// Parameters for a function are also a table instead of an ArrayList
/// because we want to resolve identifiers to them.
parameters: UnderlyingTypeMap,
symbols: SymbolTable,
env: *Environment,
/// Find a given identifier in the function. Can resolve to either a parameter
pub fn findSymbol(self: *const @This(), identifier: []const u8) ?SymbolData {

View file

@ -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(
self: *@This(),
ctx: *comp.CompilationContext,
@ -194,6 +233,14 @@ pub const TypeSolver = struct {
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
// its own can of worms
var symbols = comp.SymbolTable.init(self.allocator);