13 TypeInfo typeType(std::shared_ptr<Context> globalCtx, Type t)
\r
15 // used to differentiate basic types from user defined types
\r
17 result.isStruct = true;
\r
18 if (t.name == "int" || t.name == "float" || t.name == "double" ||
\r
19 t.name == "char" || t.name == "long" || t.name == "short" || t.name == "bool" ||
\r
22 result.isStruct = false;
\r
29 TypeInfo typeExpr(std::shared_ptr<Context> globalCtx, Expr e)
\r
35 case ExprType::Func:
\r
37 // get type info from return type
\r
38 auto f = findFunction(e._func.functionName, e._func.namespacePrefixes, globalCtx);
\r
40 throw "Unknown function";
\r
41 result = typeType(globalCtx, std::get<0>(*f).returnType);
\r
44 case ExprType::Method:
\r
46 // get type info from return type
\r
47 TypeInfo tiCaller = typeExpr(globalCtx, *e._method.expr);
\r
48 if (!tiCaller.isStruct)
\r
49 throw "Calling method on non-struct";
\r
50 auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx);
\r
52 throw "Calling method on unknown struct";
\r
53 auto m = findStructMethod(e._method.methodName, std::get<0>(*s));
\r
55 throw "Unknown method";
\r
56 result = typeType(globalCtx, m->t.returnType);
\r
60 // literal types are defined
\r
61 result.isStruct = false;
\r
62 switch (e._lit.type)
\r
64 case LitType::Bool: result.type.name = "bool"; break;
\r
65 case LitType::Int: result.type.name = "int"; break;
\r
66 case LitType::Decimal: result.type.name = "double"; break;
\r
67 case LitType::String: result.type.name = "char"; result.type.modifiers.push_back({ TypeModifierType::Pointer, false, -1 }); break;
\r
70 case ExprType::Paren:
\r
71 result = typeExpr(globalCtx, *e._paren.expr);
\r
75 // assume dot access is always member access
\r
76 // and lookup struct variable
\r
77 auto tiCaller = typeExpr(globalCtx, *e._dot.expr);
\r
78 if (!tiCaller.isStruct)
\r
79 throw "Accessing member of non-struct";
\r
80 auto s = findStruct(tiCaller.type.name, tiCaller.type.namespacePrefixes, globalCtx);
\r
82 throw "Calling method on unknown struct";
\r
83 auto sm = findStructMember(e._dot.identifier, std::get<0>(*s));
\r
84 if (!sm.has_value())
\r
85 throw "Unknown struct member";
\r
86 result = typeType(globalCtx, sm->t.type);
\r
89 case ExprType::PrefixOp:
\r
90 result = typeExpr(globalCtx, *e._prefixOp.expr);
\r
92 case ExprType::PostfixOp:
\r
93 result = typeExpr(globalCtx, *e._postfixOp.expr);
\r
95 case ExprType::BinaryOp:
\r
96 result = typeExpr(globalCtx, *e._binaryOp.lexpr);
\r
98 case ExprType::TernaryOp:
\r
99 result = typeExpr(globalCtx, *e._ternaryOp.rexprTrue);
\r
101 case ExprType::Bracket:
\r
103 // get type of expr and remove array/ptr modifier to get
\r
104 // type of [] access
\r
105 TypeInfo ti = typeExpr(globalCtx, *e._brackets.lexpr);
\r
106 if (!ti.type.modifiers.empty())
\r
109 result.type.modifiers.pop_back();
\r
113 throw "Indexing non-array";
\r
116 case ExprType::Identifier:
\r
118 // var lookup and return var type
\r
119 auto v = findVariable(e._identifier.identifier, e._identifier.namespacePrefixes, globalCtx);
\r
120 if (!v.has_value())
\r
121 throw "Unknown variable";
\r
122 result = typeType(globalCtx, std::get<0>(*v).type);
\r