[Impl] StructInstance现在记录parent TypeInfo, StructType改用TypeInfo
This commit is contained in:
@@ -20,7 +20,7 @@ namespace Fig
|
||||
|
||||
std::unordered_map<std::size_t, Function> functions;
|
||||
std::unordered_map<std::size_t, FString> functionNames;
|
||||
std::unordered_map<std::size_t, FString> structTypeNames;
|
||||
// std::unordered_map<std::size_t, FString> structTypeNames;
|
||||
|
||||
public:
|
||||
ContextPtr parent;
|
||||
@@ -49,7 +49,7 @@ namespace Fig
|
||||
variables.insert(c.variables.begin(), c.variables.end());
|
||||
functions.insert(c.functions.begin(), c.functions.end());
|
||||
functionNames.insert(c.functionNames.begin(), c.functionNames.end());
|
||||
structTypeNames.insert(c.structTypeNames.begin(), c.structTypeNames.end());
|
||||
// structTypeNames.insert(c.structTypeNames.begin(), c.structTypeNames.end());
|
||||
}
|
||||
|
||||
std::unordered_map<size_t, Function> getFunctions() const
|
||||
@@ -142,11 +142,11 @@ namespace Fig
|
||||
functions[fn.id] = fn;
|
||||
functionNames[fn.id] = name;
|
||||
}
|
||||
if (ti == ValueType::StructType)
|
||||
{
|
||||
auto &st = value->as<StructType>();
|
||||
structTypeNames[st.id] = name;
|
||||
}
|
||||
// if (ti == ValueType::StructType)
|
||||
// {
|
||||
// auto &st = value->as<StructType>();
|
||||
// structTypeNames[st.id] = name;
|
||||
// }
|
||||
}
|
||||
std::optional<Function> getFunction(std::size_t id)
|
||||
{
|
||||
@@ -180,22 +180,22 @@ namespace Fig
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
std::optional<FString> getStructName(std::size_t id)
|
||||
{
|
||||
auto it = structTypeNames.find(id);
|
||||
if (it != structTypeNames.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else if (parent)
|
||||
{
|
||||
return parent->getStructName(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
// std::optional<FString> getStructName(std::size_t id)
|
||||
// {
|
||||
// auto it = structTypeNames.find(id);
|
||||
// if (it != structTypeNames.end())
|
||||
// {
|
||||
// return it->second;
|
||||
// }
|
||||
// else if (parent)
|
||||
// {
|
||||
// return parent->getStructName(id);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return std::nullopt;
|
||||
// }
|
||||
// }
|
||||
bool contains(const FString &name)
|
||||
{
|
||||
if (variables.contains(name))
|
||||
|
||||
@@ -11,6 +11,20 @@
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
bool Evaluator::isTypeMatch(const TypeInfo &expected, ObjectPtr obj)
|
||||
{
|
||||
if (expected == ValueType::Any)
|
||||
return true;
|
||||
|
||||
TypeInfo actual = obj->getTypeInfo();
|
||||
|
||||
if (actual != ValueType::StructInstance)
|
||||
return expected == actual;
|
||||
|
||||
const StructInstance &si = obj->as<StructInstance>();
|
||||
return si.parentType == expected;
|
||||
}
|
||||
|
||||
LvObject Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
||||
{
|
||||
const FString &name = var->name;
|
||||
@@ -300,8 +314,7 @@ namespace Fig
|
||||
LvObject lv = evalLv(lexp, ctx);
|
||||
ObjectPtr rhs = eval(rexp, ctx);
|
||||
lv.set(std::make_shared<Object>(
|
||||
*(lv.get()) + *rhs
|
||||
));
|
||||
*(lv.get()) + *rhs));
|
||||
return rhs;
|
||||
}
|
||||
case Operator::MinusAssign: {
|
||||
@@ -437,7 +450,7 @@ namespace Fig
|
||||
TypeInfo expectedType(fnParas.posParas[i].second); // look up type info, if exists a type with the name, use it, else throw
|
||||
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
|
||||
TypeInfo actualType = argVal->getTypeInfo();
|
||||
if (expectedType != actualType and expectedType != ValueType::Any)
|
||||
if (!isTypeMatch(expectedType, argVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"ArgumentTypeMismatchError",
|
||||
@@ -457,7 +470,7 @@ namespace Fig
|
||||
TypeInfo expectedType = fnParas.defParas[defParamIndex].second.first;
|
||||
|
||||
ObjectPtr defaultVal = eval(fnParas.defParas[defParamIndex].second.second, ctx);
|
||||
if (expectedType != defaultVal->getTypeInfo() and expectedType != ValueType::Any)
|
||||
if (!isTypeMatch(expectedType, defaultVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"DefaultParameterTypeError",
|
||||
@@ -471,7 +484,7 @@ namespace Fig
|
||||
|
||||
ObjectPtr argVal = eval(fnArgs.argv[i], ctx);
|
||||
TypeInfo actualType = argVal->getTypeInfo();
|
||||
if (expectedType != actualType and expectedType != ValueType::Any)
|
||||
if (!isTypeMatch(expectedType, argVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"ArgumentTypeMismatchError",
|
||||
@@ -540,7 +553,7 @@ namespace Fig
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fnStruct.retType != retVal->getTypeInfo() and fnStruct.retType != ValueType::Any)
|
||||
if (!isTypeMatch(fnStruct.retType, retVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"ReturnTypeMismatchError",
|
||||
@@ -728,7 +741,7 @@ namespace Fig
|
||||
ObjectPtr defaultVal = eval(field.defaultValue, ctx); // it can't be null here
|
||||
|
||||
// type check
|
||||
if (expectedType != defaultVal->getTypeInfo() && expectedType != ValueType::Any)
|
||||
if (!isTypeMatch(expectedType, defaultVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
@@ -746,7 +759,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
const ObjectPtr &argVal = evaluatedArgs[i].second;
|
||||
if (expectedType != argVal->getTypeInfo() && expectedType != ValueType::Any)
|
||||
if (!isTypeMatch(expectedType, argVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
@@ -784,7 +797,7 @@ namespace Fig
|
||||
|
||||
// type check
|
||||
const TypeInfo &expectedType = field.type;
|
||||
if (expectedType != defaultVal->getTypeInfo() && expectedType != ValueType::Any)
|
||||
if (!isTypeMatch(expectedType, defaultVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
@@ -801,7 +814,7 @@ namespace Fig
|
||||
continue;
|
||||
}
|
||||
const ObjectPtr &argVal = evaluatedArgs[i].second;
|
||||
if (field.type != argVal->getTypeInfo() && field.type != ValueType::Any)
|
||||
if (!isTypeMatch(field.type, argVal))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
@@ -824,7 +837,7 @@ namespace Fig
|
||||
Function(fn.paras, fn.retType, fn.body, instanceCtx) // change its closureContext to struct instance's context
|
||||
));
|
||||
}
|
||||
return std::make_shared<Object>(StructInstance(structT.id, instanceCtx));
|
||||
return std::make_shared<Object>(StructInstance(structT.type, instanceCtx));
|
||||
}
|
||||
|
||||
case AstType::ListExpr: {
|
||||
@@ -905,7 +918,7 @@ namespace Fig
|
||||
else if (!declaredTypeName.empty())
|
||||
{
|
||||
declaredType = TypeInfo(declaredTypeName);
|
||||
if (value != nullptr && value->getTypeInfo() != declaredType && declaredType != ValueType::Any)
|
||||
if (value != nullptr && !isTypeMatch(declaredType, value))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
@@ -1006,12 +1019,13 @@ namespace Fig
|
||||
}
|
||||
|
||||
AccessModifier am = (stDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
|
||||
TypeInfo _(stDef->name, true); // register type name
|
||||
TypeInfo type(stDef->name, true); // register type name
|
||||
ctx->def(
|
||||
stDef->name,
|
||||
ValueType::StructType,
|
||||
am,
|
||||
std::make_shared<Object>(StructType(
|
||||
type,
|
||||
defContext,
|
||||
fields)));
|
||||
return StatementResult::normal();
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <Value/LvObject.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct StatementResult
|
||||
@@ -52,6 +51,7 @@ namespace Fig
|
||||
{
|
||||
private:
|
||||
ContextPtr global;
|
||||
|
||||
public:
|
||||
FString sourcePath;
|
||||
|
||||
@@ -84,8 +84,7 @@ namespace Fig
|
||||
name,
|
||||
ValueType::Function,
|
||||
AccessModifier::Const,
|
||||
std::make_shared<Object>(f)
|
||||
);
|
||||
std::make_shared<Object>(f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,24 +101,27 @@ namespace Fig
|
||||
val);
|
||||
}
|
||||
}
|
||||
|
||||
bool isTypeMatch(const TypeInfo &, ObjectPtr);
|
||||
|
||||
/* Left-value eval*/
|
||||
LvObject evalVarExpr(Ast::VarExpr, ContextPtr);
|
||||
LvObject evalMemberExpr(Ast::MemberExpr, ContextPtr); // a.b
|
||||
LvObject evalIndexExpr(Ast::IndexExpr, ContextPtr); // a[b]
|
||||
LvObject evalIndexExpr(Ast::IndexExpr, ContextPtr); // a[b]
|
||||
|
||||
LvObject evalLv(Ast::Expression, ContextPtr); // for access: a.b / index a[b]
|
||||
|
||||
/* Right-value eval*/
|
||||
|
||||
RvObject evalBinary(Ast::BinaryExpr, ContextPtr); // normal binary expr: +, -, *....
|
||||
RvObject evalUnary(Ast::UnaryExpr, ContextPtr); // unary expr
|
||||
RvObject evalBinary(Ast::BinaryExpr, ContextPtr); // normal binary expr: +, -, *....
|
||||
RvObject evalUnary(Ast::UnaryExpr, ContextPtr); // unary expr
|
||||
RvObject evalTernary(Ast::TernaryExpr, ContextPtr); // ternary expr
|
||||
|
||||
RvObject evalFunctionCall(const Function&, const Ast::FunctionArguments&, const FString& ,ContextPtr); // function call
|
||||
RvObject evalFunctionCall(const Function &, const Ast::FunctionArguments &, const FString &, ContextPtr); // function call
|
||||
RvObject eval(Ast::Expression, ContextPtr);
|
||||
|
||||
StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block
|
||||
StatementResult evalStatement(Ast::Statement, ContextPtr); // statement
|
||||
StatementResult evalStatement(Ast::Statement, ContextPtr); // statement
|
||||
|
||||
std::filesystem::path resolveModulePath(const std::vector<FString> &);
|
||||
ContextPtr loadModule(const std::filesystem::path &);
|
||||
|
||||
@@ -75,7 +75,8 @@ namespace Fig
|
||||
{FString(u8"else"), TokenType::Else},
|
||||
{FString(u8"struct"), TokenType::Struct},
|
||||
{FString(u8"interface"), TokenType::Interface},
|
||||
{FString(u8"implement"), TokenType::Implement},
|
||||
{FString(u8"impl"), TokenType::Implement},
|
||||
{FString(u8"is"), TokenType::Is},
|
||||
{FString(u8"public"), TokenType::Public},
|
||||
{FString(u8"return"), TokenType::Return},
|
||||
{FString(u8"break"), TokenType::Break},
|
||||
|
||||
@@ -18,14 +18,14 @@ namespace Fig
|
||||
Identifier,
|
||||
|
||||
/* Keywords */
|
||||
Package, // package
|
||||
And, // and
|
||||
Or, // or
|
||||
Not, // not
|
||||
Import, // import
|
||||
Function, // func
|
||||
Variable, // var
|
||||
Const, // const
|
||||
Package, // package
|
||||
And, // and
|
||||
Or, // or
|
||||
Not, // not
|
||||
Import, // import
|
||||
Function, // func
|
||||
Variable, // var
|
||||
Const, // const
|
||||
// Final, // final
|
||||
While, // while
|
||||
For, // for
|
||||
@@ -33,7 +33,8 @@ namespace Fig
|
||||
Else, // else
|
||||
Struct, // struct
|
||||
Interface, // interface
|
||||
Implement, // implement
|
||||
Implement, // impl
|
||||
Is, // is
|
||||
Public, // public
|
||||
Return, // return
|
||||
Break, // break
|
||||
@@ -64,7 +65,7 @@ namespace Fig
|
||||
ShiftLeft, // <<
|
||||
ShiftRight, // >>
|
||||
// Exclamation, // !
|
||||
Question, // ?
|
||||
Question, // ?
|
||||
Assign, // =
|
||||
Less, // <
|
||||
Greater, // >
|
||||
@@ -87,8 +88,8 @@ namespace Fig
|
||||
LeftBrace, // {
|
||||
RightBrace, // }
|
||||
// LeftArrow, // <-
|
||||
RightArrow, // ->
|
||||
DoubleArrow, // =>
|
||||
RightArrow, // ->
|
||||
DoubleArrow, // =>
|
||||
Equal, // ==
|
||||
NotEqual, // !=
|
||||
LessEqual, // <=
|
||||
@@ -106,7 +107,7 @@ namespace Fig
|
||||
Walrus, // :=
|
||||
Power, // **
|
||||
|
||||
TripleDot, // ... for variadic parameter
|
||||
TripleDot, // ... for variadic parameter
|
||||
};
|
||||
|
||||
class Token final
|
||||
|
||||
@@ -77,3 +77,16 @@ namespace Fig
|
||||
using StringClass = FString;
|
||||
}; // namespace ValueType
|
||||
}; // namespace Fig
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<Fig::TypeInfo>
|
||||
{
|
||||
size_t operator()(const Fig::TypeInfo &t)
|
||||
{
|
||||
return std::hash<size_t>{}(t.getInstanceID());
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,17 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <Context/context_forward.hpp>
|
||||
#include <Value/Type.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct StructInstance
|
||||
{
|
||||
size_t parentId;
|
||||
TypeInfo parentType;
|
||||
ContextPtr localContext;
|
||||
|
||||
// ===== Constructors =====
|
||||
StructInstance(size_t _parentId, ContextPtr _localContext) :
|
||||
parentId(_parentId), localContext(std::move(_localContext)) {}
|
||||
StructInstance(TypeInfo _parentType, ContextPtr _localContext) :
|
||||
parentType(_parentType), localContext(std::move(_localContext)) {}
|
||||
|
||||
StructInstance(const StructInstance &other) = default;
|
||||
StructInstance(StructInstance &&) noexcept = default;
|
||||
@@ -21,7 +22,7 @@ namespace Fig
|
||||
// ===== Comparison =====
|
||||
bool operator==(const StructInstance &other) const noexcept
|
||||
{
|
||||
return parentId == other.parentId && localContext == other.localContext;
|
||||
return parentType == other.parentType && localContext == other.localContext;
|
||||
}
|
||||
bool operator!=(const StructInstance &other) const noexcept
|
||||
{
|
||||
|
||||
@@ -33,13 +33,13 @@ namespace Fig
|
||||
|
||||
struct StructType
|
||||
{
|
||||
std::size_t id;
|
||||
TypeInfo type;
|
||||
ContextPtr defContext; // 定义时的上下文
|
||||
std::vector<Field> fields;
|
||||
|
||||
// ===== Constructors =====
|
||||
StructType(ContextPtr _defContext, std::vector<Field> _fields) :
|
||||
id(nextId()), defContext(std::move(_defContext)), fields(std::move(_fields)) {}
|
||||
StructType(TypeInfo _type, ContextPtr _defContext, std::vector<Field> _fields) :
|
||||
type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)) {}
|
||||
|
||||
StructType(const StructType &other) = default;
|
||||
StructType(StructType &&) noexcept = default;
|
||||
@@ -49,7 +49,7 @@ namespace Fig
|
||||
// ===== Comparison =====
|
||||
bool operator==(const StructType &other) const noexcept
|
||||
{
|
||||
return id == other.id;
|
||||
return type == other.type;
|
||||
}
|
||||
bool operator!=(const StructType &other) const noexcept
|
||||
{
|
||||
|
||||
@@ -58,12 +58,12 @@ namespace Fig
|
||||
return r;
|
||||
};
|
||||
const StructType &st = value->as<StructType>();
|
||||
return std::hash<std::size_t>{}(st.id) + HashFields(st.fields);
|
||||
return std::hash<TypeInfo>{}(st.type) + HashFields(st.fields);
|
||||
}
|
||||
if (type == ValueType::StructInstance)
|
||||
{
|
||||
const StructInstance &si = value->as<StructInstance>();
|
||||
return std::hash<std::size_t>{}(si.parentId) + std::hash<uint64_t>{}(reinterpret_cast<uint64_t>(std::addressof(*si.localContext)));
|
||||
return std::hash<TypeInfo>{}(si.parentType) + std::hash<uint64_t>{}(reinterpret_cast<uint64_t>(std::addressof(*si.localContext)));
|
||||
}
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -400,11 +400,11 @@ namespace Fig
|
||||
static_cast<const void *>(&as<Function>())));
|
||||
if (is<StructType>())
|
||||
return FString(std::format("<StructType {} at {:p}>",
|
||||
as<StructType>().id,
|
||||
as<StructType>().type.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<StructType>())));
|
||||
if (is<StructInstance>())
|
||||
return FString(std::format("<StructInstance '{}' at {:p}>",
|
||||
as<StructInstance>().parentId,
|
||||
as<StructInstance>().parentType.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<StructInstance>())));
|
||||
if (is<List>())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user