X-Git-Url: https://gitweb.ps.run/toc/blobdiff_plain/dbc4a22d3c8c4189459f0361cb9da06415ec2dc9..be56e29997e17685eebf8bd7cb745183c60de7db:/src/typeInfo.h diff --git a/src/typeInfo.h b/src/typeInfo.h new file mode 100644 index 0000000..3914847 --- /dev/null +++ b/src/typeInfo.h @@ -0,0 +1,115 @@ +#pragma once + +#include "repr.h" + +struct TypeInfo +{ + Type type; + bool isStruct; +}; + +#include "find.h" + +TypeInfo typeType(const Program & p, Type t) +{ + TypeInfo result; + result.isStruct = true; + if (t.name == "int" || t.name == "float" || t.name == "double" || + t.name == "char" || t.name == "long" || t.name == "short" || t.name == "bool") + { + result.isStruct = false; + } + result.type = t; + return result; +} + +TypeInfo typeExpr(const Program & p, const std::vector & globalNamespace, Expr e) +{ + TypeInfo result; + + switch (e.type) + { + case ExprType::Func: + { + auto namespacePrefixes = globalNamespace; + namespacePrefixes.insert(namespacePrefixes.end(), + e._func.namespacePrefixes.begin(), + e._func.namespacePrefixes.end()); + auto f = findFunction(p, e._func.functionName, namespacePrefixes); + if (!f.has_value()) + throw "Unknown function"; + result = typeType(p, f.value().returnType); + break; + } + case ExprType::Method: + { + TypeInfo tiCaller = typeExpr(p, globalNamespace, *e._method.expr); + auto m = findStructMethod(p, e._method.methodName, tiCaller); + if (!m.has_value()) + throw "Unknown method"; + result = typeType(p, m.value().returnType); + break; + } + case ExprType::Lit: + result.isStruct = false; + switch (e._lit.type) + { + case LitType::Bool: result.type.name = "bool"; break; + case LitType::Int: result.type.name = "int"; break; + case LitType::Decimal: result.type.name = "double"; break; + case LitType::String: result.type.name = "char"; result.type.modifiers.push_back({ TypeModifierType::Pointer, false, -1 }); break; + } + break; + case ExprType::Paren: + result = typeExpr(p, globalNamespace, *e._paren.expr); + break; + case ExprType::Dot: + { + auto sm = findStructMember(p, + typeExpr(p, globalNamespace, *e._dot.expr), e._dot.identifier); + if (!sm.has_value()) + throw "Unknown struct member"; + result = typeType(p, sm.value().type); + break; + } + case ExprType::PrefixOp: + result = typeExpr(p, globalNamespace, *e._prefixOp.expr); + break; + case ExprType::PostfixOp: + result = typeExpr(p, globalNamespace, *e._postfixOp.expr); + break; + case ExprType::BinaryOp: + result = typeExpr(p, globalNamespace, *e._binaryOp.lexpr); + break; + case ExprType::TernaryOp: + result = typeExpr(p, globalNamespace, *e._ternaryOp.rexprTrue); + break; + case ExprType::Bracket: + { + TypeInfo ti = typeExpr(p, globalNamespace, *e._brackets.lexpr); + if (!ti.type.modifiers.empty()) + { + result = ti; + result.type.modifiers.pop_back(); + } + else + { + throw "Indexing non-array"; + } + } + case ExprType::Identifier: + { + auto namespacePrefixes = globalNamespace; + namespacePrefixes.insert(namespacePrefixes.end(), + e._identifier.namespacePrefixes.begin(), + e._identifier.namespacePrefixes.end()); + auto v = findVariable(p, e._identifier.identifier, namespacePrefixes); + if (!v.has_value()) + throw "Unknown variable"; + result = typeType(p, v.value().type); + break; + } + } + + return result; +} \ No newline at end of file