挺大的改动。增加 as运算符,转换不了抛出 TypeError。import语法更新。修复try一点错误。现在表达式运算返回ExprResult。通过3个宏实现简便错误传播与解包 unwrap
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
#include "Evaluator/Core/ExprResult.hpp"
|
||||
#include <Ast/AccessModifier.hpp>
|
||||
#include <Ast/Expressions/FunctionCall.hpp>
|
||||
#include <Ast/astBase.hpp>
|
||||
@@ -37,7 +38,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
RvObject value = nullptr;
|
||||
if (varDef->expr) { value = eval(varDef->expr, ctx); }
|
||||
if (varDef->expr) { value = check_unwrap_stres(eval(varDef->expr, ctx)); }
|
||||
|
||||
TypeInfo declaredType; // default is Any
|
||||
const Ast::Expression &declaredTypeExp = varDef->declaredType;
|
||||
@@ -45,7 +46,7 @@ namespace Fig
|
||||
if (varDef->followupType) { declaredType = actualType(value); }
|
||||
else if (declaredTypeExp)
|
||||
{
|
||||
ObjectPtr declaredTypeValue = eval(declaredTypeExp, ctx);
|
||||
ObjectPtr declaredTypeValue = check_unwrap_stres(eval(declaredTypeExp, ctx));
|
||||
declaredType = actualType(declaredTypeValue);
|
||||
|
||||
if (value != nullptr && !isTypeMatch(declaredType, value, ctx))
|
||||
@@ -83,7 +84,7 @@ namespace Fig
|
||||
TypeInfo returnType = ValueType::Any;
|
||||
if (fnDef->retType)
|
||||
{
|
||||
ObjectPtr returnTypeValue = eval(fnDef->retType, ctx);
|
||||
ObjectPtr returnTypeValue = check_unwrap_stres(eval(fnDef->retType, ctx));
|
||||
returnType = actualType(returnTypeValue);
|
||||
}
|
||||
|
||||
@@ -117,7 +118,10 @@ namespace Fig
|
||||
AccessModifier am = (stDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
|
||||
|
||||
ctx->def(stDef->name, ValueType::StructType, am, structTypeObj); // predef
|
||||
defContext->def(stDef->name, ValueType::StructType, AccessModifier::Const, structTypeObj); // predef to itself, always const
|
||||
defContext->def(stDef->name,
|
||||
ValueType::StructType,
|
||||
AccessModifier::Const,
|
||||
structTypeObj); // predef to itself, always const
|
||||
|
||||
std::vector<Field> fields;
|
||||
std::vector<FString> _fieldNames;
|
||||
@@ -134,7 +138,7 @@ namespace Fig
|
||||
TypeInfo fieldType = ValueType::Any;
|
||||
if (field.declaredType)
|
||||
{
|
||||
ObjectPtr declaredTypeValue = eval(field.declaredType, ctx);
|
||||
ObjectPtr declaredTypeValue = check_unwrap_stres(eval(field.declaredType, ctx));
|
||||
fieldType = actualType(declaredTypeValue);
|
||||
}
|
||||
|
||||
@@ -239,11 +243,10 @@ namespace Fig
|
||||
*/
|
||||
if (ValueType::isTypeBuiltin(structType))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"BadUserError",
|
||||
std::format("Don't overload built-in type operators plz! `{}`", prettyType(structTypeObj).toBasicString()),
|
||||
ip
|
||||
);
|
||||
throw EvaluatorError(u8"BadUserError",
|
||||
std::format("Don't overload built-in type operators plz! `{}`",
|
||||
prettyType(structTypeObj).toBasicString()),
|
||||
ip);
|
||||
}
|
||||
|
||||
using enum Ast::Operator;
|
||||
@@ -328,7 +331,8 @@ namespace Fig
|
||||
const Ast::FunctionParameters ¶s = implMethod.paras;
|
||||
for (size_t i = 0; i < paraCnt; ++i)
|
||||
{
|
||||
const TypeInfo ¶Type = actualType(eval(paras.posParas[i].second, ctx));
|
||||
const TypeInfo ¶Type =
|
||||
actualType(check_unwrap_stres(eval(paras.posParas[i].second, ctx)));
|
||||
if (paraType != ValueType::Any && paraType != structType)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
@@ -345,7 +349,7 @@ namespace Fig
|
||||
|
||||
if (paraCnt == 1)
|
||||
{
|
||||
ctx->registerUnaryOperator(structType, op, [=, this](const ObjectPtr &value) -> ObjectPtr {
|
||||
ctx->registerUnaryOperator(structType, op, [=, this](const ObjectPtr &value) -> ExprResult {
|
||||
fillOpFnParas({value});
|
||||
return executeFunction(Function(opFnName,
|
||||
implMethod.paras, // parameters
|
||||
@@ -447,7 +451,7 @@ namespace Fig
|
||||
|
||||
implemented.insert(name);
|
||||
|
||||
ObjectPtr returnTypeValue = eval(ifMethod.returnType, ctx);
|
||||
ObjectPtr returnTypeValue = check_unwrap_stres(eval(ifMethod.returnType, ctx));
|
||||
|
||||
record.implMethods[name] =
|
||||
Function(implMethod.name, implMethod.paras, actualType(returnTypeValue), implMethod.body, ctx);
|
||||
@@ -474,7 +478,7 @@ namespace Fig
|
||||
|
||||
case IfSt: {
|
||||
auto ifSt = std::static_pointer_cast<Ast::IfSt>(stmt);
|
||||
ObjectPtr condVal = eval(ifSt->condition, ctx);
|
||||
ObjectPtr condVal = check_unwrap_stres(eval(ifSt->condition, ctx));
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
@@ -486,7 +490,7 @@ namespace Fig
|
||||
// else
|
||||
for (const auto &elif : ifSt->elifs)
|
||||
{
|
||||
ObjectPtr elifCondVal = eval(elif->condition, ctx);
|
||||
ObjectPtr elifCondVal = check_unwrap_stres(eval(elif->condition, ctx));
|
||||
if (elifCondVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
@@ -503,7 +507,7 @@ namespace Fig
|
||||
auto whileSt = std::static_pointer_cast<Ast::WhileSt>(stmt);
|
||||
while (true)
|
||||
{
|
||||
ObjectPtr condVal = eval(whileSt->condition, ctx);
|
||||
ObjectPtr condVal = check_unwrap_stres(eval(whileSt->condition, ctx));
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
@@ -535,7 +539,7 @@ namespace Fig
|
||||
while (true) // use while loop to simulate for loop, cause we
|
||||
// need to check condition type every iteration
|
||||
{
|
||||
ObjectPtr condVal = eval(forSt->condition, loopContext);
|
||||
ObjectPtr condVal = check_unwrap_stres(eval(forSt->condition, loopContext));
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
@@ -569,10 +573,15 @@ namespace Fig
|
||||
ContextPtr tryCtx = std::make_shared<Context>(
|
||||
FString(std::format("<Try at {}:{}>", tryst->getAAI().line, tryst->getAAI().column)), ctx);
|
||||
StatementResult sr = StatementResult::normal();
|
||||
bool crashed = false;
|
||||
for (auto &stmt : tryst->body->stmts)
|
||||
{
|
||||
sr = evalStatement(stmt, tryCtx); // eval in try context
|
||||
if (sr.isError()) { break; }
|
||||
if (sr.isError())
|
||||
{
|
||||
crashed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool catched = false;
|
||||
for (auto &cat : tryst->catches)
|
||||
@@ -591,7 +600,7 @@ namespace Fig
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!catched)
|
||||
if (!catched && crashed)
|
||||
{
|
||||
throw EvaluatorError(u8"UncaughtExceptionError",
|
||||
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
|
||||
@@ -604,7 +613,7 @@ namespace Fig
|
||||
case ThrowSt: {
|
||||
auto ts = std::static_pointer_cast<Ast::ThrowSt>(stmt);
|
||||
|
||||
ObjectPtr value = eval(ts->value, ctx);
|
||||
ObjectPtr value = check_unwrap_stres(eval(ts->value, ctx));
|
||||
if (value->is<ValueType::NullClass>())
|
||||
{
|
||||
throw EvaluatorError(u8"TypeError", u8"Why did you throw a null?", ts);
|
||||
@@ -616,7 +625,7 @@ namespace Fig
|
||||
auto returnSt = std::static_pointer_cast<Ast::ReturnSt>(stmt);
|
||||
|
||||
ObjectPtr returnValue = Object::getNullInstance(); // default is null
|
||||
if (returnSt->retValue) returnValue = eval(returnSt->retValue, ctx);
|
||||
if (returnSt->retValue) returnValue = check_unwrap_stres(eval(returnSt->retValue, ctx));
|
||||
return StatementResult::returnFlow(returnValue);
|
||||
}
|
||||
|
||||
@@ -646,7 +655,7 @@ namespace Fig
|
||||
|
||||
case ExpressionStmt: {
|
||||
auto exprStmt = std::static_pointer_cast<Ast::ExpressionStmtAst>(stmt);
|
||||
return StatementResult::normal(eval(exprStmt->exp, ctx));
|
||||
return check_unwrap_stres(eval(exprStmt->exp, ctx));
|
||||
}
|
||||
|
||||
case BlockStatement: {
|
||||
|
||||
Reference in New Issue
Block a user