add get expr analysis
- rename GetExpr.struc to GetExpr.target
This commit is contained in:
parent
64e39a6f1e
commit
fc9f5d9ce0
5 changed files with 47 additions and 14 deletions
|
@ -128,7 +128,7 @@ pub const StructExpr = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const GetExpr = struct {
|
pub const GetExpr = struct {
|
||||||
struc: *Expr,
|
target: *Expr,
|
||||||
name: Token,
|
name: Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -272,7 +272,7 @@ pub fn printExpr(expr: *const Expr) void {
|
||||||
|
|
||||||
.Get => |get| {
|
.Get => |get| {
|
||||||
warn("(");
|
warn("(");
|
||||||
printExpr(get.struc);
|
printExpr(get.target);
|
||||||
warn(".{})", get.name.lexeme);
|
warn(".{})", get.name.lexeme);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ fn prettyType(typ: SymbolUnderlyingType) []const u8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn printScope(scope: *Scope, ident: usize) void {
|
pub fn printScope(scope: *Scope, ident: usize) void {
|
||||||
print(ident, "scope at addr {}\n", scope);
|
print(ident, "scope at addr {}\n", &scope);
|
||||||
|
|
||||||
var it = scope.env.iterator();
|
var it = scope.env.iterator();
|
||||||
while (it.next()) |kv| {
|
while (it.next()) |kv| {
|
||||||
|
@ -405,7 +405,7 @@ pub fn printContext(ctx: CompilationContext) void {
|
||||||
|
|
||||||
// go through scopes
|
// go through scopes
|
||||||
std.debug.warn("scope info:\n");
|
std.debug.warn("scope info:\n");
|
||||||
printScope(fn_sym.scope, 0);
|
printScope(fn_sym.scope, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
.Struct => |typemap| {
|
.Struct => |typemap| {
|
||||||
|
|
|
@ -121,10 +121,9 @@ pub const Codegen = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
.Get => |get| {
|
.Get => |get| {
|
||||||
// TODO rename get.struc to get.target
|
var target = get.target.*;
|
||||||
var struc = get.struc.*;
|
|
||||||
|
|
||||||
switch (struc) {
|
switch (target) {
|
||||||
.Variable => |vari| {
|
.Variable => |vari| {
|
||||||
// first, we must check if the target is a type
|
// first, we must check if the target is a type
|
||||||
// and emit accordingly
|
// and emit accordingly
|
||||||
|
@ -158,7 +157,7 @@ pub const Codegen = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
else => {
|
else => {
|
||||||
std.debug.warn("Invalid get target: {}\n", ast.ExprType(struc));
|
std.debug.warn("Invalid get target: {}\n", ast.ExprType(target));
|
||||||
return CompileError.EmitError;
|
return CompileError.EmitError;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,11 +320,11 @@ pub const Parser = struct {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkGet(self: *@This(), struc: *Expr, name: Token) !*Expr {
|
fn mkGet(self: *@This(), target: *Expr, name: Token) !*Expr {
|
||||||
var expr = try self.allocator.create(Expr);
|
var expr = try self.allocator.create(Expr);
|
||||||
expr.* = Expr{
|
expr.* = Expr{
|
||||||
.Get = ast.GetExpr{
|
.Get = ast.GetExpr{
|
||||||
.struc = struc,
|
.target = target,
|
||||||
.name = name,
|
.name = name,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -906,11 +906,11 @@ pub const Parser = struct {
|
||||||
return self.doError("can not initialize struct field");
|
return self.doError("can not initialize struct field");
|
||||||
},
|
},
|
||||||
|
|
||||||
.Equal => return try self.mkSet(get.struc, get.name, value),
|
.Equal => return try self.mkSet(get.target, get.name, value),
|
||||||
|
|
||||||
.PlusEqual, .MinusEqual, .StarEqual, .SlashEqual => {
|
.PlusEqual, .MinusEqual, .StarEqual, .SlashEqual => {
|
||||||
return try self.mkSet(
|
return try self.mkSet(
|
||||||
get.struc,
|
get.target,
|
||||||
get.name,
|
get.name,
|
||||||
try self.mkBinary(expr, binop.?, value),
|
try self.mkBinary(expr, binop.?, value),
|
||||||
);
|
);
|
||||||
|
|
|
@ -159,9 +159,43 @@ pub const TypeSolver = struct {
|
||||||
return func_sym.return_type;
|
return func_sym.return_type;
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO variable resolution
|
// TODO analysis for .Variable
|
||||||
|
|
||||||
// TODO Get (for structs and enums)
|
.Get => |get| {
|
||||||
|
var target = get.target.*;
|
||||||
|
if (ast.ExprType(target) != .Variable) {
|
||||||
|
std.debug.warn("Expected Variable as get target, got {}\n", ast.ExprType(target));
|
||||||
|
return CompileError.TypeError;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lexeme = target.Variable.lexeme;
|
||||||
|
var global_typ_opt = self.resolveGlobalType(ctx, lexeme);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - name resolution for when global_typ is null + analysis of
|
||||||
|
// the name's type
|
||||||
|
// - analysis for structs
|
||||||
|
|
||||||
|
if (global_typ_opt == null) @panic("TODO name resolution");
|
||||||
|
|
||||||
|
var global_typ = global_typ_opt.?;
|
||||||
|
|
||||||
|
switch (global_typ) {
|
||||||
|
|
||||||
|
// TODO we need to fetch the given
|
||||||
|
// struct field (on get.name) type and return it
|
||||||
|
.Struct => @panic("TODO analysis of struct"),
|
||||||
|
.Enum => return global_typ,
|
||||||
|
else => {
|
||||||
|
std.debug.warn(
|
||||||
|
"Expected Struct/Enum as get target, got {}\n",
|
||||||
|
comp.SymbolUnderlyingTypeEnum(global_typ),
|
||||||
|
);
|
||||||
|
|
||||||
|
return CompileError.TypeError;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
else => {
|
else => {
|
||||||
std.debug.warn("TODO resolve expr {}\n", ast.ExprType(expr.*));
|
std.debug.warn("TODO resolve expr {}\n", ast.ExprType(expr.*));
|
||||||
|
|
Loading…
Reference in a new issue