aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2020-11-15 21:32:10 +0100
committerDanielGavin <danielgavin5@hotmail.com>2020-11-15 21:32:10 +0100
commit0ead9be9ada93eff3b754faf58432a152e7e26be (patch)
tree12f9d02fe3990a51dcef5a9d8ebff1121b190da8 /src
parent9a3ecb59bc74a9c60964bfd0300d2d977c426a07 (diff)
array index works, started work on generics
Diffstat (limited to 'src')
-rw-r--r--src/index/clone.odin3
-rw-r--r--src/index/indexer.odin2
-rw-r--r--src/index/symbol.odin10
-rw-r--r--src/server/analysis.odin136
4 files changed, 145 insertions, 6 deletions
diff --git a/src/index/clone.odin b/src/index/clone.odin
index 2354b8a..0dcb0b9 100644
--- a/src/index/clone.odin
+++ b/src/index/clone.odin
@@ -5,6 +5,7 @@ import "core:fmt"
import "core:odin/tokenizer"
import "core:odin/ast"
import "core:strings"
+import "core:log"
clone_type :: proc{
clone_node,
@@ -165,7 +166,7 @@ clone_node :: proc(node: ^ast.Node, allocator := context.allocator) -> ^ast.Node
r := cast(^Typeid_Type)res;
r.specialization = clone_type(r.specialization, allocator);
case:
- fmt.panicf("Unhandled node kind: %T", n);
+ log.error("Unhandled node kind: %T", n);
}
return res;
diff --git a/src/index/indexer.odin b/src/index/indexer.odin
index 88e5419..2d80751 100644
--- a/src/index/indexer.odin
+++ b/src/index/indexer.odin
@@ -46,7 +46,7 @@ indexer: Indexer;
lookup :: proc(name: string, scope: string) -> (Symbol, bool) {
symbol, ok := memory_index_lookup(&indexer.static_index, name, scope);
- //log.infof("lookup name: %v scope: %v, symbol %v", name, scope, symbol);
+ log.infof("lookup name: %v scope: %v, symbol %v", name, scope, symbol);
return symbol, ok;
}
diff --git a/src/index/symbol.odin b/src/index/symbol.odin
index b0501b1..bc75d81 100644
--- a/src/index/symbol.odin
+++ b/src/index/symbol.odin
@@ -27,6 +27,7 @@ SymbolStructValue :: struct {
types: [] ^ast.Expr,
};
+
SymbolPackageValue :: struct {
};
@@ -36,10 +37,18 @@ SymbolProcedureValue :: struct {
arg_types: [] ^ast.Field,
};
+/*
+ Generic symbol that is used by the indexer for any variable type(constants, defined global variables, etc),
+*/
+SymbolGenericValue :: struct {
+ expr: ^ast.Expr,
+};
+
SymbolValue :: union {
SymbolStructValue,
SymbolPackageValue,
SymbolProcedureValue,
+ SymbolGenericValue,
};
Symbol :: struct {
@@ -56,6 +65,7 @@ Symbol :: struct {
SymbolType :: enum {
Function = 3,
Field = 5,
+ Variable = 6,
Package = 9, //set by ast symbol
Keyword = 14, //set by ast symbol
Struct = 22,
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 7d07e23..b54e165 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -40,6 +40,7 @@ AstContext :: struct {
document_package: string,
use_globals: bool,
use_locals: bool,
+ call: ^ast.Expr, //used to determene the types for generics and the correct function for overloaded functions
};
make_ast_context :: proc(file: ast.File, imports: [] Package, package_name: string, allocator := context.temp_allocator) -> AstContext {
@@ -62,6 +63,65 @@ tokenizer_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) {
}
+resolve_poly_spec :: proc {
+ resolve_poly_spec_node,
+};
+
+resolve_poly_spec_node :: proc(ast_context: ^AstContext, call_node: ^ast.Node, spec_node: ^ast.Node) {
+
+
+}
+
+
+/*
+ Figure out which function the call expression is using out of the list from proc group
+ */
+resolve_function_overload :: proc(ast_context: ^AstContext, group: ast.Proc_Group) -> (index.Symbol, bool) {
+
+
+
+ return index.Symbol {}, false;
+}
+
+resolve_generic_function :: proc(ast_context: ^AstContext, proc_lit: ast.Proc_Lit) -> (index.Symbol, bool) {
+
+ using ast;
+
+ if proc_lit.type.params == nil {
+ return index.Symbol {}, false;
+ }
+
+
+ call_expr := ast_context.call.derived.(Call_Expr);
+ poly_map := make(map[string]^Expr, 0, context.temp_allocator);
+ i := 0;
+
+
+ for param in proc_lit.type.params.list {
+
+ for name in param.names {
+
+ if poly, ok := name.derived.(Poly_Type); ok {
+ poly_map[poly.type.name] = call_expr.args[i];
+ }
+
+ if poly, ok := param.type.derived.(Poly_Type); ok {
+
+ arr := poly.specialization.derived.(Array_Type);
+
+ log.info(arr.elem.derived);
+ }
+
+ i += 1;
+ }
+
+ }
+
+
+ return index.Symbol {}, false;
+}
+
+
resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr, expect_identifier := true) -> (index.Symbol, bool) {
using ast;
@@ -69,8 +129,23 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr, expec
switch v in node.derived {
case Ident:
return resolve_type_identifier(ast_context, v, expect_identifier);
+ case Index_Expr:
+ indexed, ok := resolve_type_expression(ast_context, v.expr, false);
+
+ if generic, ok := indexed.value.(index.SymbolGenericValue); ok {
+
+ switch c in generic.expr.derived {
+ case Array_Type:
+ return resolve_type_expression(ast_context, c.elem, false);
+
+ }
+
+ }
+
+ return index.Symbol {}, false;
case Call_Expr:
- return resolve_type_expression(ast_context, v.expr);
+ ast_context.call = node;
+ return resolve_type_expression(ast_context, v.expr, false);
case Selector_Expr:
if selector, ok := resolve_type_expression(ast_context, v.expr); ok {
@@ -108,12 +183,15 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr, expec
else {
return index.Symbol {}, false;
}
+ case:
+ log.errorf("Unhandled node kind: %T", v);
}
return index.Symbol {}, false;
}
+
/*
Function recusively goes through the identifier until it hits a struct, enum, procedure literals, since you can
have chained variable declarations. ie. a := foo { test = 2}; b := a; c := b;
@@ -122,6 +200,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec
using ast;
+ //note(Daniel, if global and local ends up being 100% same just make a function that takes the map)
if local, ok := ast_context.locals[node.name]; ast_context.use_locals && ok {
switch v in local.derived {
@@ -130,7 +209,14 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec
case Struct_Type:
return make_symbol_struct_from_ast(ast_context, v), !expect_identifier;
case Proc_Lit:
- return make_symbol_procedure_from_ast(ast_context, v, node.name), !expect_identifier;
+ if !v.type.generic {
+ return make_symbol_procedure_from_ast(ast_context, v, node.name), !expect_identifier;
+ }
+ else {
+ return resolve_generic_function(ast_context, v);
+ }
+ case Proc_Group:
+ return resolve_function_overload(ast_context, v);
case Selector_Expr:
if ident, ok := v.expr.derived.(Ident); ok {
@@ -146,6 +232,12 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec
}
return index.Symbol {}, false;
+ case Array_Type:
+ return make_symbol_generic_from_ast(ast_context, local), true;
+ case Index_Expr:
+ return resolve_type_expression(ast_context, local, false);
+ case:
+ log.errorf("Unhandled node kind: %T", v);
}
}
@@ -157,7 +249,14 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec
case Struct_Type:
return make_symbol_struct_from_ast(ast_context, v), !expect_identifier;
case Proc_Lit:
- return make_symbol_procedure_from_ast(ast_context, v, node.name), !expect_identifier;
+ if !v.type.generic {
+ return make_symbol_procedure_from_ast(ast_context, v, node.name), !expect_identifier;
+ }
+ else {
+ return resolve_generic_function(ast_context, v);
+ }
+ case Proc_Group:
+ return resolve_function_overload(ast_context, v);
case Selector_Expr:
if ident, ok := v.expr.derived.(Ident); ok {
@@ -172,6 +271,12 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident, expec
}
return index.Symbol {}, false;
+ case Array_Type:
+ return make_symbol_generic_from_ast(ast_context, global), true;
+ case Index_Expr:
+ return resolve_type_expression(ast_context, global, false);
+ case:
+ log.errorf("Unhandled node kind: %T", v);
}
}
@@ -291,6 +396,21 @@ make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, v: ast.Proc_Lit
return symbol;
}
+make_symbol_generic_from_ast :: proc(ast_context: ^AstContext, expr: ^ast.Expr) -> index.Symbol {
+
+ symbol := index.Symbol {
+ range = common.get_token_range(expr, ast_context.file.src),
+ type = .Variable,
+ };
+
+ symbol.value = index.SymbolGenericValue {
+ expr = expr,
+ };
+
+ return symbol;
+}
+
+
make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type) -> index.Symbol {
symbol := index.Symbol {
@@ -329,11 +449,15 @@ get_globals :: proc(file: ast.File, ast_context: ^AstContext) {
str := common.get_ast_node_string(name, file.src);
+
+
if value_decl.type != nil {
ast_context.globals[str] = value_decl.type;
+ //log.infof("name: %v, %v", str, value_decl.type.derived);
}
else {
+ //log.infof("name: %v, %v", str, value_decl.values[i].derived);
ast_context.globals[str] = value_decl.values[i];
}
@@ -377,6 +501,10 @@ get_locals_value_decl :: proc(file: ast.File, value_decl: ast.Value_Decl, ast_co
case Comp_Lit:
append(&results, v.type);
+ case Proc_Group:
+
+ case:
+ append(&results, value);
}
}
@@ -940,7 +1068,7 @@ get_document_position_node :: proc(node: ^ast.Node, position_context: ^DocumentP
get_document_position(n.key, position_context);
get_document_position(n.value, position_context);
case:
- fmt.panicf("Unhandled node kind: %T", n);
+ log.errorf("Unhandled node kind: %T", n);
}
} \ No newline at end of file