[VER] 0.3.4-alpha

[FEAT] 异常系统, try/catch/finally
This commit is contained in:
2025-12-30 17:42:41 +08:00
parent 6982f169aa
commit 9f24392034
13 changed files with 857 additions and 470 deletions

View File

@@ -52,10 +52,10 @@ AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true AlwaysBreakTemplateDeclarations: true
# false表示函数实参要么都在同一行要么都各自一行 # false表示函数实参要么都在同一行要么都各自一行
BinPackArguments: true BinPackArguments: false
# false表示所有形参要么都在同一行要么都各自一行 # false表示所有形参要么都在同一行要么都各自一行
BinPackParameters: true BinPackParameters: false
# 大括号换行只有当BreakBeforeBraces设置为Custom时才有效 # 大括号换行只有当BreakBeforeBraces设置为Custom时才有效
BraceWrapping: BraceWrapping:
@@ -108,12 +108,12 @@ BreakConstructorInitializers: AfterColon
BreakStringLiterals: false BreakStringLiterals: false
# 每行字符的限制0表示没有限制 # 每行字符的限制0表示没有限制
ColumnLimit: 0 ColumnLimit: 80
CompactNamespaces: true CompactNamespaces: true
# 构造函数的初始化列表要么都在同一行,要么都各自一行 # 构造函数的初始化列表要么都在同一行,要么都各自一行
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: true
# 构造函数的初始化列表的缩进宽度 # 构造函数的初始化列表的缩进宽度
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4

View File

@@ -2,7 +2,7 @@
"name": "fig-vscode", "name": "fig-vscode",
"displayName": "Fig Language", "displayName": "Fig Language",
"description": "VSCode extension for Fig language with syntax highlighting", "description": "VSCode extension for Fig language with syntax highlighting",
"version": "0.0.1", "version": "0.0.2",
"publisher": "PuqiAR", "publisher": "PuqiAR",
"engines": { "engines": {
"vscode": "^1.90.0" "vscode": "^1.90.0"

View File

@@ -57,7 +57,7 @@
"patterns": [ "patterns": [
{ {
"name": "keyword.control.fig", "name": "keyword.control.fig",
"match": "\\b(and|or|not|import|func|var|const|final|while|for|if|else|struct|interface|implement|public|return|break|continue)\\b" "match": "\\b(and|or|not|import|func|var|const|final|while|for|if|else|struct|interface|impl|public|return|break|continue|try|catch|throw)\\b"
}, },
{ "name": "constant.language.fig", "match": "\\b(true|false|null)\\b" } { "name": "constant.language.fig", "match": "\\b(true|false|null)\\b" }
] ]
@@ -78,7 +78,7 @@
}, },
{ {
"name": "keyword.operator.comparison.fig", "name": "keyword.operator.comparison.fig",
"match": "(==|!=|<=|>=|<|>)" "match": "(==|!=|<=|>=|<|>|is)"
}, },
{ {
"name": "punctuation.separator.fig", "name": "punctuation.separator.fig",

View File

@@ -0,0 +1,64 @@
#pragma once
#include <Ast/astBase.hpp>
namespace Fig::Ast
{
class ThrowSt final : public StatementAst
{
public:
Expression value;
ThrowSt()
{
type = AstType::ThrowSt;
}
ThrowSt(Expression _value) :
value(std::move(_value))
{
type = AstType::ThrowSt;
}
};
using Throw = std::shared_ptr<ThrowSt>;
struct Catch
{
FString errVarName;
bool hasType = false;
FString errVarType;
BlockStatement body;
Catch() {}
Catch(FString _errVarName, FString _errVarType, BlockStatement _body) :
errVarName(std::move(_errVarName)), errVarType(std::move(_errVarType)), body(std::move(_body))
{
hasType = true;
}
Catch(FString _errVarName, BlockStatement _body) :
errVarName(std::move(_errVarName)), body(std::move(_body))
{
hasType = false;
}
};
class TrySt final : public StatementAst
{
public:
BlockStatement body;
std::vector<Catch> catches;
BlockStatement finallyBlock = nullptr;
TrySt()
{
type = AstType::TrySt;
}
TrySt(BlockStatement _body, std::vector<Catch> _catches, BlockStatement _finallyBlock) :
body(std::move(_body)), catches(std::move(_catches)), finallyBlock(std::move(_finallyBlock))
{
type = AstType::TrySt;
}
};
using Try = std::shared_ptr<TrySt>;
} // namespace Fig::Ast

View File

@@ -15,6 +15,8 @@
#include <Ast/Expressions/ValueExpr.hpp> #include <Ast/Expressions/ValueExpr.hpp>
#include <Ast/Expressions/VarExpr.hpp> #include <Ast/Expressions/VarExpr.hpp>
#include <Ast/Statements/ControlSt.hpp>
#include <Ast/Statements/ErrorFlow.hpp>
#include <Ast/Statements/VarDef.hpp> #include <Ast/Statements/VarDef.hpp>
#include <Ast/Statements/WhileSt.hpp> #include <Ast/Statements/WhileSt.hpp>
#include <Ast/Statements/StructDefSt.hpp> #include <Ast/Statements/StructDefSt.hpp>
@@ -23,6 +25,5 @@
#include <Ast/Statements/ImportSt.hpp> #include <Ast/Statements/ImportSt.hpp>
#include <Ast/Statements/InterfaceDefSt.hpp> #include <Ast/Statements/InterfaceDefSt.hpp>
#include <Ast/Statements/FunctionDefSt.hpp> #include <Ast/Statements/FunctionDefSt.hpp>
#include <Ast/Statements/ControlSt.hpp>
#include <Ast/Statements/ExpressionStmt.hpp> #include <Ast/Statements/ExpressionStmt.hpp>
#include <Ast/Statements/ForSt.hpp> #include <Ast/Statements/ForSt.hpp>

View File

@@ -60,6 +60,9 @@ namespace Fig::Ast
PackageSt, PackageSt,
ImportSt, ImportSt,
TrySt,
ThrowSt,
}; };
// static const std::unordered_map<AstType, FString> astTypeToString{ // static const std::unordered_map<AstType, FString> astTypeToString{
@@ -210,6 +213,7 @@ namespace Fig::Ast
LessEqual, // <= LessEqual, // <=
Greater, // > Greater, // >
GreaterEqual, // >= GreaterEqual, // >=
Is, // a is b
// 三目 // 三目
TernaryCond, TernaryCond,
@@ -254,6 +258,7 @@ namespace Fig::Ast
Operator::LessEqual, Operator::LessEqual,
Operator::Greater, Operator::Greater,
Operator::GreaterEqual, Operator::GreaterEqual,
Operator::Is,
Operator::BitAnd, Operator::BitAnd,
Operator::BitOr, Operator::BitOr,
@@ -297,6 +302,7 @@ namespace Fig::Ast
{TokenType::LessEqual, Operator::LessEqual}, {TokenType::LessEqual, Operator::LessEqual},
{TokenType::Greater, Operator::Greater}, {TokenType::Greater, Operator::Greater},
{TokenType::GreaterEqual, Operator::GreaterEqual}, {TokenType::GreaterEqual, Operator::GreaterEqual},
{TokenType::Is, Operator::Is},
// 三目 // 三目
{TokenType::Question, Operator::TernaryCond}, {TokenType::Question, Operator::TernaryCond},

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,8 @@ namespace Fig
Normal, Normal,
Return, Return,
Break, Break,
Continue Continue,
Error
} flow; } flow;
StatementResult(ObjectPtr val, Flow f = Flow::Normal) : StatementResult(ObjectPtr val, Flow f = Flow::Normal) :
@@ -43,11 +44,16 @@ namespace Fig
{ {
return StatementResult(Object::getNullInstance(), Flow::Continue); return StatementResult(Object::getNullInstance(), Flow::Continue);
} }
static StatementResult errorFlow(ObjectPtr val)
{
return StatementResult(val, Flow::Error);
}
bool isNormal() const { return flow == Flow::Normal; } bool isNormal() const { return flow == Flow::Normal; }
bool shouldReturn() const { return flow == Flow::Return; } bool shouldReturn() const { return flow == Flow::Return; }
bool shouldBreak() const { return flow == Flow::Break; } bool shouldBreak() const { return flow == Flow::Break; }
bool shouldContinue() const { return flow == Flow::Continue; } bool shouldContinue() const { return flow == Flow::Continue; }
bool isError() const { return flow == Flow::Error; }
}; };
class Evaluator class Evaluator

View File

@@ -81,7 +81,10 @@ namespace Fig
{FString(u8"return"), TokenType::Return}, {FString(u8"return"), TokenType::Return},
{FString(u8"break"), TokenType::Break}, {FString(u8"break"), TokenType::Break},
{FString(u8"continue"), TokenType::Continue}, {FString(u8"continue"), TokenType::Continue},
{FString(u8"try"), TokenType::Try},
{FString(u8"catch"), TokenType::Catch},
{FString(u8"throw"), TokenType::Throw},
{FString(u8"Finally"), TokenType::Finally},
// {FString(u8"Null"), TokenType::TypeNull}, // {FString(u8"Null"), TokenType::TypeNull},
// {FString(u8"Int"), TokenType::TypeInt}, // {FString(u8"Int"), TokenType::TypeInt},

View File

@@ -1,5 +1,7 @@
#pragma once #pragma once
#include "Ast/Statements/InterfaceDefSt.hpp"
#include "Ast/functionParameters.hpp"
#include <Core/fig_string.hpp> #include <Core/fig_string.hpp>
#include <Value/value.hpp> #include <Value/value.hpp>
@@ -15,13 +17,40 @@ namespace Fig
{ {
namespace Builtins namespace Builtins
{ {
const TypeInfo ErrorInterfaceTypeInfo(u8"Error", true);
/*
// error's interface like:
interface Error
{
toString() -> String;
getErrorClass() -> String;
getErrorMessage() -> String;
}
*/
const std::unordered_map<FString, ObjectPtr> builtinValues = { const std::unordered_map<FString, ObjectPtr> builtinValues = {
{u8"null", Object::getNullInstance()}, {u8"null", Object::getNullInstance()},
{u8"true", Object::getTrueInstance()}, {u8"true", Object::getTrueInstance()},
{u8"false", Object::getFalseInstance()}, {u8"false", Object::getFalseInstance()},
{u8"Error",
std::make_shared<Object>(InterfaceType(
ErrorInterfaceTypeInfo,
{Ast::InterfaceMethod(u8"toString",
Ast::FunctionParameters({}, {}),
u8"String",
nullptr),
Ast::InterfaceMethod(u8"getErrorClass",
Ast::FunctionParameters({}, {}),
u8"String",
nullptr),
Ast::InterfaceMethod(u8"getErrorMessage",
Ast::FunctionParameters({}, {}),
u8"String",
nullptr)}))},
}; };
using BuiltinFunction = std::function<ObjectPtr(const std::vector<ObjectPtr> &)>; using BuiltinFunction =
std::function<ObjectPtr(const std::vector<ObjectPtr> &)>;
const std::unordered_map<FString, int> builtinFunctionArgCounts = { const std::unordered_map<FString, int> builtinFunctionArgCounts = {
{u8"__fstdout_print", -1}, // variadic {u8"__fstdout_print", -1}, // variadic
@@ -67,35 +96,46 @@ namespace Fig
}; };
const std::unordered_map<FString, BuiltinFunction> builtinFunctions{ const std::unordered_map<FString, BuiltinFunction> builtinFunctions{
{u8"__fstdout_print", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fstdout_print",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
for (auto arg : args) for (auto arg : args)
{ {
std::print("{}", arg->toStringIO().toBasicString()); std::print("{}", arg->toStringIO().toBasicString());
} }
return std::make_shared<Object>(ValueType::IntClass(args.size())); return std::make_shared<Object>(
ValueType::IntClass(args.size()));
}}, }},
{u8"__fstdout_println", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fstdout_println",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
for (auto arg : args) for (auto arg : args)
{ {
std::print("{}", arg->toStringIO().toBasicString()); std::print("{}", arg->toStringIO().toBasicString());
} }
std::print("\n"); std::print("\n");
return std::make_shared<Object>(ValueType::IntClass(args.size())); return std::make_shared<Object>(
ValueType::IntClass(args.size()));
}}, }},
{u8"__fstdin_read", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fstdin_read",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
std::string input; std::string input;
std::cin >> input; std::cin >> input;
return std::make_shared<Object>(FString::fromBasicString(input)); return std::make_shared<Object>(
FString::fromBasicString(input));
}}, }},
{u8"__fstdin_readln", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fstdin_readln",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
std::string line; std::string line;
std::getline(std::cin, line); std::getline(std::cin, line);
return std::make_shared<Object>(FString::fromBasicString(line)); return std::make_shared<Object>(
FString::fromBasicString(line));
}}, }},
{u8"__fvalue_type", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fvalue_type",
return std::make_shared<Object>(args[0]->getTypeInfo().toString()); [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
return std::make_shared<Object>(
args[0]->getTypeInfo().toString());
}}, }},
{u8"__fvalue_int_parse", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fvalue_int_parse",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
FString str = args[0]->as<ValueType::StringClass>(); FString str = args[0]->as<ValueType::StringClass>();
try try
{ {
@@ -104,203 +144,252 @@ namespace Fig
} }
catch (...) catch (...)
{ {
throw RuntimeError(FString(std::format("Invalid int string for parsing", str.toBasicString()))); throw RuntimeError(
FString(std::format("Invalid int string for parsing",
str.toBasicString())));
} }
}}, }},
{u8"__fvalue_int_from", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fvalue_int_from",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
if (val->is<ValueType::DoubleClass>()) if (val->is<ValueType::DoubleClass>())
{ {
return std::make_shared<Object>(static_cast<ValueType::IntClass>(val->as<ValueType::DoubleClass>())); return std::make_shared<Object>(
static_cast<ValueType::IntClass>(
val->as<ValueType::DoubleClass>()));
} }
else if (val->is<ValueType::BoolClass>()) else if (val->is<ValueType::BoolClass>())
{ {
return std::make_shared<Object>(static_cast<ValueType::IntClass>(val->as<ValueType::BoolClass>() ? 1 : 0)); return std::make_shared<Object>(
static_cast<ValueType::IntClass>(
val->as<ValueType::BoolClass>() ? 1 : 0));
} }
else else
{ {
throw RuntimeError(FString(std::format("Type '{}' cannot be converted to int", val->getTypeInfo().toString().toBasicString()))); throw RuntimeError(FString(std::format(
"Type '{}' cannot be converted to int",
val->getTypeInfo().toString().toBasicString())));
} }
}}, }},
{u8"__fvalue_double_parse", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fvalue_double_parse",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
FString str = args[0]->as<ValueType::StringClass>(); FString str = args[0]->as<ValueType::StringClass>();
try try
{ {
ValueType::DoubleClass val = std::stod(str.toBasicString()); ValueType::DoubleClass val =
return std::make_shared<Object>(ValueType::DoubleClass(val)); std::stod(str.toBasicString());
return std::make_shared<Object>(
ValueType::DoubleClass(val));
} }
catch (...) catch (...)
{ {
throw RuntimeError(FString(std::format("Invalid double string for parsing", str.toBasicString()))); throw RuntimeError(FString(
std::format("Invalid double string for parsing",
str.toBasicString())));
} }
}}, }},
{u8"__fvalue_double_from", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fvalue_double_from",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
if (val->is<ValueType::IntClass>()) if (val->is<ValueType::IntClass>())
{ {
return std::make_shared<Object>(static_cast<ValueType::DoubleClass>(val->as<ValueType::IntClass>())); return std::make_shared<Object>(
static_cast<ValueType::DoubleClass>(
val->as<ValueType::IntClass>()));
} }
else if (val->is<ValueType::BoolClass>()) else if (val->is<ValueType::BoolClass>())
{ {
return std::make_shared<Object>(ValueType::DoubleClass(val->as<ValueType::BoolClass>() ? 1.0 : 0.0)); return std::make_shared<Object>(ValueType::DoubleClass(
val->as<ValueType::BoolClass>() ? 1.0 : 0.0));
} }
else else
{ {
throw RuntimeError(FString(std::format("Type '{}' cannot be converted to double", val->getTypeInfo().toString().toBasicString()))); throw RuntimeError(FString(std::format(
"Type '{}' cannot be converted to double",
val->getTypeInfo().toString().toBasicString())));
} }
}}, }},
{u8"__fvalue_string_from", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fvalue_string_from",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
return std::make_shared<Object>(val->toStringIO()); return std::make_shared<Object>(val->toStringIO());
}}, }},
/* math start */ /* math start */
{u8"__fmath_acos", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_acos",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(acos(d)); return std::make_shared<Object>(acos(d));
}}, }},
{u8"__fmath_acosh", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_acosh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(acosh(d)); return std::make_shared<Object>(acosh(d));
}}, }},
{u8"__fmath_asin", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_asin",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(asin(d)); return std::make_shared<Object>(asin(d));
}}, }},
{u8"__fmath_asinh", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_asinh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(asinh(d)); return std::make_shared<Object>(asinh(d));
}}, }},
{u8"__fmath_atan", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_atan",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(atan(d)); return std::make_shared<Object>(atan(d));
}}, }},
{u8"__fmath_atan2", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_atan2",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass y = args[0]->getNumericValue(); ValueType::DoubleClass y = args[0]->getNumericValue();
ValueType::DoubleClass x = args[1]->getNumericValue(); ValueType::DoubleClass x = args[1]->getNumericValue();
return std::make_shared<Object>(atan2(y, x)); return std::make_shared<Object>(atan2(y, x));
}}, }},
{u8"__fmath_atanh", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_atanh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(atanh(d)); return std::make_shared<Object>(atanh(d));
}}, }},
{u8"__fmath_ceil", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_ceil",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(ceil(d)); return std::make_shared<Object>(ceil(d));
}}, }},
{u8"__fmath_cos", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_cos",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(cos(d)); return std::make_shared<Object>(cos(d));
}}, }},
{u8"__fmath_cosh", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_cosh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(cosh(d)); return std::make_shared<Object>(cosh(d));
}}, }},
{u8"__fmath_exp", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_exp",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(exp(d)); return std::make_shared<Object>(exp(d));
}}, }},
{u8"__fmath_expm1", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_expm1",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(expm1(d)); return std::make_shared<Object>(expm1(d));
}}, }},
{u8"__fmath_fabs", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_fabs",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(fabs(d)); return std::make_shared<Object>(fabs(d));
}}, }},
{u8"__fmath_floor", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_floor",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(floor(d)); return std::make_shared<Object>(floor(d));
}}, }},
{u8"__fmath_fmod", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_fmod",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue();
return std::make_shared<Object>(fmod(x, y)); return std::make_shared<Object>(fmod(x, y));
}}, }},
{u8"__fmath_frexp", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_frexp",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
int e; int e;
return std::make_shared<Object>(List( return std::make_shared<Object>(
{std::make_shared<Object>(frexp(d, &e)), List({std::make_shared<Object>(frexp(d, &e)),
std::make_shared<Object>(static_cast<ValueType::IntClass>(e))})); std::make_shared<Object>(
static_cast<ValueType::IntClass>(e))}));
}}, }},
{u8"__fmath_gcd", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_gcd",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::IntClass x = args[0]->as<ValueType::IntClass>(); ValueType::IntClass x = args[0]->as<ValueType::IntClass>();
ValueType::IntClass y = args[1]->as<ValueType::IntClass>(); ValueType::IntClass y = args[1]->as<ValueType::IntClass>();
return std::make_shared<Object>(std::gcd(x, y)); return std::make_shared<Object>(std::gcd(x, y));
}}, }},
{u8"__fmath_hypot", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_hypot",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue();
return std::make_shared<Object>(hypot(x, y)); return std::make_shared<Object>(hypot(x, y));
}}, }},
{u8"__fmath_isequal", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_isequal",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue();
static const double epsilon = 1e-9; static const double epsilon = 1e-9;
return std::make_shared<Object>( return std::make_shared<Object>(fabs(x - y) < epsilon);
fabs(x - y) < epsilon
);
}}, }},
{u8"__fmath_log", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_log",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log(d)); return std::make_shared<Object>(log(d));
}}, }},
{u8"__fmath_log10", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_log10",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log10(d)); return std::make_shared<Object>(log10(d));
}}, }},
{u8"__fmath_log1p", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_log1p",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log1p(d)); return std::make_shared<Object>(log1p(d));
}}, }},
{u8"__fmath_log2", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_log2",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log2(d)); return std::make_shared<Object>(log2(d));
}}, }},
{u8"__fmath_sin", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_sin",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sin(d)); return std::make_shared<Object>(sin(d));
}}, }},
{u8"__fmath_sinh", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_sinh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sinh(d)); return std::make_shared<Object>(sinh(d));
}}, }},
{u8"__fmath_sqrt", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_sqrt",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sqrt(d)); return std::make_shared<Object>(sqrt(d));
}}, }},
{u8"__fmath_tan", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_tan",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(tan(d)); return std::make_shared<Object>(tan(d));
}}, }},
{u8"__fmath_tanh", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_tanh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(tanh(d)); return std::make_shared<Object>(tanh(d));
}}, }},
{u8"__fmath_trunc", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_trunc",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(trunc(d)); return std::make_shared<Object>(trunc(d));
@@ -317,7 +406,8 @@ namespace Fig
auto it = builtinFunctions.find(name); auto it = builtinFunctions.find(name);
if (it == builtinFunctions.end()) if (it == builtinFunctions.end())
{ {
throw RuntimeError(FString(std::format("Builtin function '{}' not found", name.toBasicString()))); throw RuntimeError(FString(std::format(
"Builtin function '{}' not found", name.toBasicString())));
} }
return it->second; return it->second;
} }
@@ -327,7 +417,8 @@ namespace Fig
auto it = builtinFunctionArgCounts.find(name); auto it = builtinFunctionArgCounts.find(name);
if (it == builtinFunctionArgCounts.end()) if (it == builtinFunctionArgCounts.end())
{ {
throw RuntimeError(FString(std::format("Builtin function '{}' not found", name.toBasicString()))); throw RuntimeError(FString(std::format(
"Builtin function '{}' not found", name.toBasicString())));
} }
return it->second; return it->second;
} }

View File

@@ -1,3 +1,4 @@
#include "Ast/Statements/ErrorFlow.hpp"
#include "Ast/Statements/ImplementSt.hpp" #include "Ast/Statements/ImplementSt.hpp"
#include "Ast/astBase.hpp" #include "Ast/astBase.hpp"
#include "Ast/functionParameters.hpp" #include "Ast/functionParameters.hpp"
@@ -30,6 +31,7 @@ namespace Fig
{Ast::Operator::LessEqual, {8, 9}}, {Ast::Operator::LessEqual, {8, 9}},
{Ast::Operator::Greater, {8, 9}}, {Ast::Operator::Greater, {8, 9}},
{Ast::Operator::GreaterEqual, {8, 9}}, {Ast::Operator::GreaterEqual, {8, 9}},
{Ast::Operator::Is, {8, 9}},
// 位运算 // 位运算
{Ast::Operator::BitAnd, {6, 7}}, {Ast::Operator::BitAnd, {6, 7}},
@@ -478,6 +480,89 @@ namespace Fig
return makeAst<Ast::ImplementAst>(interfaceName, structName, methods); return makeAst<Ast::ImplementAst>(interfaceName, structName, methods);
} }
Ast::Throw Parser::__parseThrow()
{
// entry: current is `throw`
next(); // consume `throw`
Ast::Expression exp = parseExpression(0);
expect(TokenType::Semicolon);
next(); // consume `;`
return makeAst<Ast::ThrowSt>(exp);
}
Ast::Try Parser::__parseTry()
{
// entry: current is `try`
next(); // consume `try`
/*
try
{
...
}
catch(e: IOError)
{
}
catch(e: TimeOutError)
{
}
*/
expect(TokenType::LeftBrace);
Ast::BlockStatement body = __parseBlockStatement();
std::vector<Ast::Catch> catches;
Ast::BlockStatement finallyBlock = nullptr;
while (true)
{
if (isThis(TokenType::Catch))
{
next(); // consume `catch`
expect(TokenType::LeftParen);
next(); // consume `(`
expect(TokenType::Identifier, u8"error receive var name");
FString errVarName = currentToken().getValue();
next(); // consume name
bool hasType = false;
FString errVarType;
if (isThis(TokenType::Colon)) // :
{
next();
expect(TokenType::Identifier, u8"error type");
errVarType = currentToken().getValue();
next(); // consume var type
hasType = true;
}
expect(TokenType::RightParen); //
next(); // consume `)`
expect(TokenType::LeftBrace); // {
Ast::BlockStatement catchBody = __parseBlockStatement();
if (hasType)
{
catches.push_back(Ast::Catch(errVarName, errVarType, catchBody));
}
else {
catches.push_back(Ast::Catch(errVarName, catchBody));
}
}
else if (isThis(TokenType::Finally))
{
if (finallyBlock != nullptr)
{
throw SyntaxError(u8"Duplicate try finally-block", currentAAI.line, currentAAI.column);
}
next(); // consume `finally`
expect(TokenType::LeftBrace);
finallyBlock = __parseBlockStatement();
}
else
{
break;
}
}
return makeAst<Ast::TrySt>(body, catches, finallyBlock);
}
Ast::Statement Parser::__parseStatement() Ast::Statement Parser::__parseStatement()
{ {
Ast::Statement stmt; Ast::Statement stmt;
@@ -568,6 +653,14 @@ namespace Fig
{ {
stmt = __parseContinue(); stmt = __parseContinue();
} }
else if (isThis(TokenType::Throw))
{
stmt = __parseThrow();
}
else if (isThis(TokenType::Try))
{
stmt = __parseTry();
}
else else
{ {
// expression statement // expression statement

View File

@@ -6,6 +6,7 @@
#include <Error/error.hpp> #include <Error/error.hpp>
#include <print> #include <print>
#include <source_location>
#include <unordered_map> #include <unordered_map>
#include <stack> #include <stack>
@@ -211,43 +212,43 @@ namespace Fig
return ptr; return ptr;
} }
void expectPeek(TokenType type) void expectPeek(TokenType type, std::source_location loc = std::source_location::current())
{ {
if (peekToken().getType() != type) if (peekToken().getType() != type)
{ {
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`", throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type), magic_enum::enum_name(type),
magic_enum::enum_name(peekToken().getType())))); magic_enum::enum_name(peekToken().getType()))), loc);
} }
} }
void expect(TokenType type) void expect(TokenType type, std::source_location loc = std::source_location::current())
{ {
if (currentToken().getType() != type) if (currentToken().getType() != type)
{ {
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`", throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type), magic_enum::enum_name(type),
magic_enum::enum_name(currentToken().getType())))); magic_enum::enum_name(currentToken().getType()))), loc);
} }
} }
void expectPeek(TokenType type, FString expected) void expectPeek(TokenType type, FString expected, std::source_location loc = std::source_location::current())
{ {
if (peekToken().getType() != type) if (peekToken().getType() != type)
{ {
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`", throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(), expected.toBasicString(),
magic_enum::enum_name(peekToken().getType())))); magic_enum::enum_name(peekToken().getType()))), loc);
} }
} }
void expect(TokenType type, FString expected) void expect(TokenType type, FString expected, std::source_location loc = std::source_location::current())
{ {
if (currentToken().getType() != type) if (currentToken().getType() != type)
{ {
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`", throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(), expected.toBasicString(),
magic_enum::enum_name(currentToken().getType())))); magic_enum::enum_name(currentToken().getType()))), loc);
} }
} }
@@ -316,6 +317,9 @@ namespace Fig
Ast::InterfaceDef __parseInterfaceDef(bool); // entry: current is Token::Identifier (interface name) arg(isPublic: bool) Ast::InterfaceDef __parseInterfaceDef(bool); // entry: current is Token::Identifier (interface name) arg(isPublic: bool)
Ast::Implement __parseImplement(); // entry: current is `impl` Ast::Implement __parseImplement(); // entry: current is `impl`
Ast::Throw __parseThrow(); // entry: current is `throw`
Ast::Try __parseTry(); // entry: current is `try`
Ast::BinaryExpr __parseInfix(Ast::Expression, Ast::Operator, Precedence); Ast::BinaryExpr __parseInfix(Ast::Expression, Ast::Operator, Precedence);
Ast::UnaryExpr __parsePrefix(Ast::Operator, Precedence); Ast::UnaryExpr __parsePrefix(Ast::Operator, Precedence);
Ast::Expression __parseCall(Ast::Expression); Ast::Expression __parseCall(Ast::Expression);

View File

@@ -39,6 +39,10 @@ namespace Fig
Return, // return Return, // return
Break, // break Break, // break
Continue, // continue Continue, // continue
Try, // try
Catch, // catch
Throw, // throw
Finally, // finally
// TypeNull, // Null // TypeNull, // Null
// TypeInt, // Int // TypeInt, // Int