[VER] 0.3.4-alpha
[FEAT] 异常系统, try/catch/finally
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
64
src/Ast/Statements/ErrorFlow.hpp
Normal file
64
src/Ast/Statements/ErrorFlow.hpp
Normal 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
|
||||||
@@ -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>
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user