10 Commits

76 changed files with 4124 additions and 1824 deletions

View File

@@ -29,16 +29,22 @@ jobs:
git clone https://git.fig-lang.cn/${{ github.repository }} .
git checkout ${{ github.ref }}
- name: 设置版本
- name: 设置版本和提交信息
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ inputs.version }}"
else
VERSION="${GITHUB_REF#refs/tags/}"
VERSION="${{ github.ref_name }}"
fi
echo "构建版本: $VERSION"
echo "VERSION=$VERSION" >> $GITHUB_ENV
# 拿提交消息
COMMIT_MSG=$(git log -3 --pretty=%B)
echo "COMMIT_MSG<<EOF" >> $GITHUB_ENV
echo "$COMMIT_MSG" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: 构建项目 (Linux)
run: |
echo "开始构建Linux版本..."
@@ -83,48 +89,74 @@ jobs:
GITEA_TOKEN: ${{ secrets.CI_TOKEN }}
run: |
VERSION="${{ env.VERSION }}"
if [ -z "$VERSION" ]; then
VERSION="${{ github.ref_name }}"
fi
COMMIT_MSG="${{ env.COMMIT_MSG }}"
API="https://git.fig-lang.cn/api/v1/repos/${{ github.repository }}"
echo "正在为Linux版本创建/更新发布 $VERSION ..."
echo "正在检查版本 $VERSION 的发布状态..."
RESPONSE=$(curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"tag_name\":\"$VERSION\",\"name\":\"Fig $VERSION\",\"draft\":false,\"prerelease\":false}" \
"$API/releases" 2>/dev/null || echo '{"id":0}')
# 准备 JSON 数据
VERSION="$VERSION" COMMIT_MSG="$COMMIT_MSG" python3 -c "import json, os; print(json.dumps({'tag_name': os.environ.get('VERSION', ''), 'name': 'Fig ' + os.environ.get('VERSION', ''), 'body': os.environ.get('COMMIT_MSG', ''), 'draft': False, 'prerelease': False}))" > release_body.json
RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
# 1. 尝试获取已有发布
RESPONSE_TAG=$(curl -sS -H "Authorization: token $GITEA_TOKEN" "$API/releases/tags/$VERSION" 2>/dev/null || echo '{"id":0}')
RELEASE_ID=$(echo "$RESPONSE_TAG" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "0" ]; then
echo "尝试通过标签获取已有发布的ID..."
RELEASE_ID=$(curl -sS -H "Authorization: token $GITEA_TOKEN" \
"$API/releases/tags/$VERSION" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "0" ]; then
echo "✅ 找到已有发布 (ID: $RELEASE_ID),正在更新说明..."
curl -sS -X PATCH -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d @release_body.json \
"$API/releases/$RELEASE_ID" > /dev/null
else
echo "未找到已有发布,准备创建新发布..."
RESPONSE=$(curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d @release_body.json \
"$API/releases" 2>/dev/null || echo '{"id":0}')
RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "0" ]; then
# 再次尝试获取,防止并发冲突
RESPONSE_TAG=$(curl -sS -H "Authorization: token $GITEA_TOKEN" "$API/releases/tags/$VERSION" 2>/dev/null || echo '{"id":0}')
RELEASE_ID=$(echo "$RESPONSE_TAG" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
fi
fi
if [ -z "$RELEASE_ID" ]; then
echo "错误:无法获取或创建发布 ID"
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "0" ]; then
echo "错误:无法获取或创建发布 ID"
exit 1
fi
echo "使用发布 ID: $RELEASE_ID 进行上传"
echo "使用发布 ID: $RELEASE_ID 进行上传"
# 上传语言包
# 上传资产
PACKAGE_ZIP="Fig-$VERSION-linux-x86_64.tar.gz"
PACKAGE_SHA="Fig-$VERSION-linux-x86_64.sha256"
echo "正在上传 $PACKAGE_ZIP ..."
curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @Fig-$VERSION-linux-x86_64.tar.gz \
"$API/releases/$RELEASE_ID/assets?name=Fig-$VERSION-linux-x86_64.tar.gz"
--data-binary "@$PACKAGE_ZIP" \
"$API/releases/$RELEASE_ID/assets?name=$PACKAGE_ZIP" > /dev/null
echo "正在上传 $PACKAGE_SHA ..."
curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: text/plain" \
--data-binary @Fig-$VERSION-linux-x86_64.sha256 \
"$API/releases/$RELEASE_ID/assets?name=Fig-$VERSION-linux-x86_64.sha256"
--data-binary "@$PACKAGE_SHA" \
"$API/releases/$RELEASE_ID/assets?name=$PACKAGE_SHA" > /dev/null
# 🔧 新增:上传Linux安装器
if [ -f "Installer/ConsoleInstaller/dist/linux/FigSetup-Linux" ]; then
# 🔧 上传Linux安装器
INSTALLER="Installer/ConsoleInstaller/dist/linux/FigSetup-Linux"
if [ -f "$INSTALLER" ]; then
echo "正在上传Linux安装器..."
curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @Installer/ConsoleInstaller/dist/linux/FigSetup-Linux \
"$API/releases/$RELEASE_ID/assets?name=FigSetup-Linux"
--data-binary "@$INSTALLER" \
"$API/releases/$RELEASE_ID/assets?name=FigSetup-Linux" > /dev/null
fi
echo "✅ Linux版本发布完成"
@@ -151,9 +183,9 @@ jobs:
run: |
$env:Path = "C:\Program Files\Git\cmd;$env:Path"
git clone https://git.fig-lang.cn/$env:GITHUB_REPOSITORY .
git checkout $env:GITHUB_REF
git checkout ${{ github.ref }}
- name: 设置版本
- name: 设置版本和提交信息
run: |
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') {
@@ -161,10 +193,16 @@ jobs:
if (-not $VERSION) { $VERSION = $env:VERSION_INPUT }
if (-not $VERSION) { $VERSION = "dev-build" }
} else {
$VERSION = $env:GITHUB_REF_NAME
$VERSION = "${{ github.ref_name }}"
}
Write-Host "构建版本: $VERSION"
"VERSION=$VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
# 确保无 BOM 的 UTF8
[System.IO.File]::AppendAllText($env:GITHUB_ENV, "VERSION=$VERSION`n")
# 提交消息
$COMMIT_MSG = git log -3 --pretty=%B
[System.IO.File]::AppendAllText($env:GITHUB_ENV, "COMMIT_MSG<<EOF`n$COMMIT_MSG`nEOF`n")
- name: 构建项目 (Windows Native)
run: |
@@ -186,14 +224,11 @@ jobs:
run: |
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# 🔧 修改:与发布步骤使用相同的版本号计算逻辑
if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') {
$VERSION = $env:INPUT_VERSION
if (-not $VERSION) { $VERSION = "dev-build" }
} else {
$VERSION = $env:GITHUB_REF_NAME
$VERSION = $env:VERSION
if (-not $VERSION) {
$VERSION = "${{ github.ref_name }}"
Write-Host "⚠️ 警告:从环境变量获取 VERSION 失败,回退到 github.ref_name: $VERSION"
}
Write-Host "打包版本: $VERSION"
$PACKAGE_NAME = "Fig-${VERSION}-windows-x86_64"
@@ -231,91 +266,100 @@ jobs:
run: |
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# 重新计算版本号(不使用 $env:VERSION
if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') {
$VERSION = $env:INPUT_VERSION
if (-not $VERSION) { $VERSION = "dev-build" }
} else {
$VERSION = $env:GITHUB_REF_NAME
$VERSION = $env:VERSION
$COMMIT_MSG = $env:COMMIT_MSG
if (-not $VERSION) {
$VERSION = "${{ github.ref_name }}"
Write-Host "⚠️ 警告:从环境变量获取 VERSION 失败,回退到 github.ref_name: $VERSION"
}
Write-Host "正在上传Windows版本到发布: $VERSION"
if (-not $VERSION) {
Write-Host "❌ 错误:版本号仍然为空,无法创建发布。"
exit 1
}
$REPO = $env:GITHUB_REPOSITORY
$API = "https://git.fig-lang.cn/api/v1/repos/$REPO"
$TOKEN = $env:GITEA_TOKEN
$HEADERS = @{
Authorization = "token $TOKEN"
'Content-Type' = 'application/json'
}
# 🔧 新增:检查必需的文件是否存在
$ZIP_FILE = "Fig-$VERSION-windows-x86_64.zip"
$HASH_FILE = "Fig-$VERSION-windows-x86_64.sha256"
$INSTALLER_PATH = "Installer\ConsoleInstaller\dist\windows\FigSetup.exe"
if (-not (Test-Path $ZIP_FILE)) {
Write-Host "❌ 错误找不到ZIP文件 $ZIP_FILE"
Get-ChildItem *.zip
exit 1
}
Write-Host "正在为Windows版本创建/更新发布 $VERSION ..."
# 🔧 关键修改直接创建发布不先检查与Linux逻辑一致
$CREATE_BODY = @{
tag_name = $VERSION
name = "Fig $VERSION"
body = $COMMIT_MSG
draft = $false
prerelease = $false
} | ConvertTo-Json -Compress
Write-Host "创建发布请求体: $CREATE_BODY"
Write-Host "正在检查版本 $VERSION 的发布状态..."
$RELEASE_ID = $null
# 直接创建发布Gitea会自动处理重复创建
$RESPONSE = Invoke-RestMethod -Method Post -Uri "$API/releases" `
-Headers @{
Authorization = "token $TOKEN"
'Content-Type' = 'application/json'
} -Body $CREATE_BODY -ErrorAction SilentlyContinue
if (-not $RESPONSE -or -not $RESPONSE.id) {
# 如果创建失败尝试通过标签获取已有发布的ID
Write-Host "创建失败,尝试获取已有发布..."
$RESPONSE = Invoke-RestMethod -Uri "$API/releases/tags/$VERSION" `
-Headers @{Authorization = "token $TOKEN" } `
-ErrorAction SilentlyContinue
try {
$EXISTING = Invoke-RestMethod -Uri "$API/releases/tags/$VERSION" -Headers $HEADERS -ErrorAction Stop
if ($EXISTING -and $EXISTING.id) {
$RELEASE_ID = $EXISTING.id
Write-Host "✅ 找到已有发布 (ID: $RELEASE_ID),正在更新..."
Invoke-RestMethod -Method Patch -Uri "$API/releases/$RELEASE_ID" -Headers $HEADERS -Body $CREATE_BODY -ErrorAction Stop | Out-Null
}
} catch {
Write-Host "未找到已有发布,准备创建新发布..."
}
if ($RESPONSE -and $RESPONSE.id) {
$RELEASE_ID = $RESPONSE.id
Write-Host "✅ 使用发布 ID: $RELEASE_ID 进行上传"
} else {
Write-Host "❌ 错误:无法获取或创建发布 ID"
exit 1
if (-not $RELEASE_ID) {
try {
Write-Host "正在创建新发布: $VERSION ..."
$RESPONSE = Invoke-RestMethod -Method Post -Uri "$API/releases" -Headers $HEADERS -Body $CREATE_BODY -ErrorAction Stop
$RELEASE_ID = $RESPONSE.id
Write-Host "✅ 发布创建成功 (ID: $RELEASE_ID)"
} catch {
$err = $_.Exception.Message
Write-Host "❌ 创建发布失败: $err"
# 最后一次尝试:再次尝试按标签获取,防止由于并发导致的冲突
try {
$RETRY = Invoke-RestMethod -Uri "$API/releases/tags/$VERSION" -Headers $HEADERS -ErrorAction Stop
$RELEASE_ID = $RETRY.id
Write-Host "✅ 重试获取发布成功 (ID: $RELEASE_ID)"
} catch {
Write-Host "❌ 无法获取或创建发布 ID"
exit 1
}
}
}
# 上传资产
Write-Host "正在上传 ZIP 文件..."
Invoke-RestMethod -Method Post -Uri "$API/releases/$RELEASE_ID/assets?name=$ZIP_FILE" `
-Headers @{
Authorization = "token $TOKEN"
'Content-Type' = 'application/octet-stream'
} -InFile $ZIP_FILE -ErrorAction SilentlyContinue
Write-Host "正在上传文件..."
$ASSETS = @(
@{ Name = $ZIP_FILE; Path = $ZIP_FILE; ContentType = "application/octet-stream" },
@{ Name = $HASH_FILE; Path = $HASH_FILE; ContentType = "text/plain" }
)
Write-Host "正在上传校验文件..."
Invoke-RestMethod -Method Post -Uri "$API/releases/$RELEASE_ID/assets?name=$HASH_FILE" `
-Headers @{
Authorization = "token $TOKEN"
'Content-Type' = 'text/plain'
} -InFile $HASH_FILE -ErrorAction SilentlyContinue
# 上传Windows安装器
if (Test-Path $INSTALLER_PATH) {
Write-Host "正在上传Windows安装器..."
Invoke-RestMethod -Method Post -Uri "$API/releases/$RELEASE_ID/assets?name=FigSetup.exe" `
-Headers @{
Authorization = "token $TOKEN"
'Content-Type' = 'application/octet-stream'
} -InFile $INSTALLER_PATH -ErrorAction SilentlyContinue
} else {
Write-Host "⚠️ 警告:未找到安装器文件 $INSTALLER_PATH"
$ASSETS += @{ Name = "FigSetup.exe"; Path = $INSTALLER_PATH; ContentType = "application/octet-stream" }
}
foreach ($asset in $ASSETS) {
Write-Host "正在上传 $($asset.Name) ..."
try {
# 如果资产已存在Gitea 可能会报错,这里简单处理
Invoke-RestMethod -Method Post -Uri "$API/releases/$RELEASE_ID/assets?name=$($asset.Name)" `
-Headers @{ Authorization = "token $TOKEN"; 'Content-Type' = $asset.ContentType } `
-InFile $asset.Path -ErrorAction SilentlyContinue | Out-Null
} catch {
Write-Host "⚠️ 上传 $($asset.Name) 失败,可能已存在。"
}
}
Write-Host "✅ Windows版本发布完成"

View File

@@ -2,3 +2,14 @@ import std.io;
import token {Token, TokenType};
import tokenizer {Tokenizer};
const src := "abc egaD";
const tokenizer := new Tokenizer{src};
const result := tokenizer.TokenizeAll();
for var i := 0; i < result.length(); i += 1
{
const tok := result[i];
io.printf("{}: {}\n", tok.literal, tok.type);
}

View File

@@ -8,13 +8,95 @@ Copyright (C) 2020-2026 PuqiAR
import token {Token, TokenType};
func list_contains(lst: List, value: Any) -> Bool
{
for var i := 0; i < lst.length(); i += 1
{
if lst[i] == value
{
return true;
}
}
return false;
}
func isspace(c: String) -> Bool
{
return c == " " || c == "\n" || c == "\t";
}
func isalpha(c: String) -> Bool
{
const alb := [
"a", "b", "c", "d",
"e", "f", "g", "h",
"i", "j", "k", "l",
"m", "n", "o", "p",
"q", "r", "s", "t",
"u", "v", "w", "x",
"y", "z",
"A", "B", "C", "D",
"E", "F", "G", "H",
"I", "J", "K", "L",
"M", "N", "O", "P",
"Q", "R", "S", "T",
"U", "V", "W", "X",
"Y", "Z"
];
return list_contains(alb, c);
}
public struct Tokenizer
{
src: String = "";
idx: Int = 0;
func next() -> Null
{
idx += 1;
}
func hasNext() -> Bool
{
return idx < src.length();
}
func produce() -> String
{
const tmp := src[idx];
idx += 1;
return tmp;
}
func current() -> String
{
return src[idx];
}
public func TokenizeAll() -> List
{
var output := [];
const push := func (tok: Token) => output.push(tok);
while hasNext()
{
while hasNext() && isspace(current())
{
next();
}
if isalpha(current())
{
var identi := "";
while hasNext() && isalpha(current())
{
identi += produce();
}
push(new Token{identi, TokenType.Identifier});
}
}
return output;
}
}

View File

@@ -34,6 +34,12 @@ Recommend view on Gitea Endpoint
1. Clone the repository:
```bash
git clone https://git.fig-lang.cn/PuqiAR/Fig.git
# Recommend
```
or
```bash
git clone https://github.com/PuqiAR/Fig.git
```

View File

@@ -26,10 +26,17 @@
### 使用教程
1. 克隆存储库:
```bash
git clone https://git.fig-lang.cn/PuqiAR/Fig.git
# 推荐
```
```bash
git clone https://github.com/PuqiAR/Fig.git
```
2. 切换到项目目录:
```bash

View File

@@ -24,31 +24,26 @@ namespace Fig::Ast
Expression callee;
FunctionArguments arg;
FunctionCallExpr()
FunctionCallExpr() { type = AstType::FunctionCall; }
FunctionCallExpr(Expression _callee, FunctionArguments _arg) : callee(std::move(_callee)), arg(std::move(_arg))
{
type = AstType::FunctionCall;
}
FunctionCallExpr(Expression _callee, FunctionArguments _arg) :
callee(std::move(_callee)), arg(std::move(_arg))
virtual String toString() override
{
type = AstType::FunctionCall;
}
virtual FString toString() override
{
FString s = callee->toString();
s += u8"(";
String s = callee->toString();
s += U"(";
for (size_t i = 0; i < arg.argv.size(); ++i)
{
s += arg.argv[i]->toString();
if (i + 1 < arg.argv.size())
s += u8", ";
if (i + 1 < arg.argv.size()) s += U",";
}
s += u8")";
s += U")";
return s;
}
};
using FunctionCall = std::shared_ptr<FunctionCallExpr>;
}; // namespace Fig
}; // namespace Fig::Ast

View File

@@ -2,7 +2,7 @@
#include <Ast/astBase.hpp>
#include <Ast/functionParameters.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <variant>
namespace Fig::Ast
@@ -25,20 +25,11 @@ namespace Fig::Ast
type = AstType::FunctionLiteralExpr;
}
bool isExprMode() const
{
return std::holds_alternative<Expression>(body);
}
bool isExprMode() const { return std::holds_alternative<Expression>(body); }
BlockStatement &getBlockBody()
{
return std::get<BlockStatement>(body);
}
BlockStatement &getBlockBody() { return std::get<BlockStatement>(body); }
Expression &getExprBody()
{
return std::get<Expression>(body);
}
Expression &getExprBody() { return std::get<Expression>(body); }
~FunctionLiteralExprAst() = default;
};

View File

@@ -9,7 +9,7 @@ namespace Fig::Ast
public:
Expression structe;
std::vector<std::pair<FString, Expression>> args;
std::vector<std::pair<String, Expression>> args;
enum class InitMode
{
@@ -25,12 +25,9 @@ namespace Fig::Ast
.3 Person {name, age, sex};
*/
InitExprAst()
{
type = AstType::InitExpr;
}
InitExprAst() { type = AstType::InitExpr; }
InitExprAst(Expression _structe, std::vector<std::pair<FString, Expression>> _args, InitMode _initMode) :
InitExprAst(Expression _structe, std::vector<std::pair<String, Expression>> _args, InitMode _initMode) :
structe(std::move(_structe)), args(std::move(_args)), initMode(_initMode)
{
type = AstType::InitExpr;

View File

@@ -11,15 +11,11 @@ namespace Fig::Ast
{
public:
Expression base;
FString member;
String member;
MemberExprAst()
{
type = AstType::MemberExpr;
}
MemberExprAst() { type = AstType::MemberExpr; }
MemberExprAst(Expression _base, FString _member) :
base(std::move(_base)), member(std::move(_member))
MemberExprAst(Expression _base, String _member) : base(std::move(_base)), member(std::move(_member))
{
type = AstType::MemberExpr;
}
@@ -33,13 +29,9 @@ namespace Fig::Ast
Expression base;
Expression index;
IndexExprAst()
{
type = AstType::IndexExpr;
}
IndexExprAst() { type = AstType::IndexExpr; }
IndexExprAst(Expression _base, Expression _index) :
base(std::move(_base)), index(std::move(_index))
IndexExprAst(Expression _base, Expression _index) : base(std::move(_base)), index(std::move(_index))
{
type = AstType::IndexExpr;
}

View File

@@ -7,18 +7,10 @@ namespace Fig::Ast
class VarExprAst final : public ExpressionAst
{
public:
const FString name;
VarExprAst() :
name(u8"")
{
type = AstType::VarExpr;
}
VarExprAst(FString _name) :
name(std::move(_name))
{
type = AstType::VarExpr;
}
const String name;
VarExprAst() : name(U"") { type = AstType::VarExpr; }
VarExprAst(String _name) : name(std::move(_name)) { type = AstType::VarExpr; }
};
using VarExpr = std::shared_ptr<VarExprAst>;
}; // namespace Fig
}; // namespace Fig::Ast

View File

@@ -9,34 +9,26 @@ namespace Fig::Ast
public:
Expression value;
ThrowSt()
{
type = AstType::ThrowSt;
}
ThrowSt() { type = AstType::ThrowSt; }
ThrowSt(Expression _value) :
value(std::move(_value))
{
type = AstType::ThrowSt;
}
ThrowSt(Expression _value) : value(std::move(_value)) { type = AstType::ThrowSt; }
};
using Throw = std::shared_ptr<ThrowSt>;
struct Catch
{
FString errVarName;
String errVarName;
bool hasType = false;
FString errVarType;
String errVarType;
BlockStatement body;
Catch() {}
Catch(FString _errVarName, FString _errVarType, BlockStatement _body) :
Catch(String _errVarName, String _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))
Catch(String _errVarName, BlockStatement _body) : errVarName(std::move(_errVarName)), body(std::move(_body))
{
hasType = false;
}
@@ -49,10 +41,7 @@ namespace Fig::Ast
std::vector<Catch> catches;
BlockStatement finallyBlock = nullptr;
TrySt()
{
type = AstType::TrySt;
}
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))
{

View File

@@ -20,17 +20,15 @@ namespace Fig::Ast
class FunctionDefSt final : public StatementAst // for definition
{
public:
FString name;
String name;
FunctionParameters paras;
bool isPublic;
Expression retType;
BlockStatement body;
FunctionDefSt()
{
type = AstType::FunctionDefSt;
}
FunctionDefSt(FString _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body)
FunctionDefSt() { type = AstType::FunctionDefSt; }
FunctionDefSt(
String _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body)
{
type = AstType::FunctionDefSt;
@@ -42,4 +40,4 @@ namespace Fig::Ast
}
};
using FunctionDef = std::shared_ptr<FunctionDefSt>;
}; // namespace Fig
}; // namespace Fig::Ast

View File

@@ -8,19 +8,9 @@ namespace Fig::Ast
{
public:
BlockStatement body;
ElseSt()
{
type = AstType::ElseSt;
}
ElseSt(BlockStatement _body) :
body(_body)
{
type = AstType::ElseSt;
}
virtual FString toString() override
{
return FString(std::format("<Else Ast at {}:{}>", aai.line, aai.column));
}
ElseSt() { type = AstType::ElseSt; }
ElseSt(BlockStatement _body) : body(_body) { type = AstType::ElseSt; }
virtual String toString() override { return String(std::format("<Else Ast at {}:{}>", aai.line, aai.column)); }
};
using Else = std::shared_ptr<ElseSt>;
class ElseIfSt final : public StatementAst
@@ -28,19 +18,14 @@ namespace Fig::Ast
public:
Expression condition;
BlockStatement body;
ElseIfSt()
ElseIfSt() { type = AstType::ElseIfSt; }
ElseIfSt(Expression _condition, BlockStatement _body) : condition(_condition), body(_body)
{
type = AstType::ElseIfSt;
}
ElseIfSt(Expression _condition,
BlockStatement _body) :
condition(_condition), body(_body)
virtual String toString() override
{
type = AstType::ElseIfSt;
}
virtual FString toString() override
{
return FString(std::format("<ElseIf Ast at {}:{}>", aai.line, aai.column));
return String(std::format("<ElseIf Ast at {}:{}>", aai.line, aai.column));
}
};
using ElseIf = std::shared_ptr<ElseIfSt>;
@@ -51,18 +36,12 @@ namespace Fig::Ast
BlockStatement body;
std::vector<ElseIf> elifs;
Else els;
IfSt()
{
type = AstType::IfSt;
}
IfSt(Expression _condition,
BlockStatement _body,
std::vector<ElseIf> _elifs,
Else _els) :
IfSt() { type = AstType::IfSt; }
IfSt(Expression _condition, BlockStatement _body, std::vector<ElseIf> _elifs, Else _els) :
condition(_condition), body(_body), elifs(_elifs), els(_els)
{
type = AstType::IfSt;
}
};
using If = std::shared_ptr<IfSt>;
}; // namespace Fig
}; // namespace Fig::Ast

View File

@@ -17,7 +17,7 @@ namespace Fig::Ast
*/
struct ImplementMethod
{
FString name;
String name;
FunctionParameters paras;
BlockStatement body;
};
@@ -25,17 +25,14 @@ namespace Fig::Ast
class ImplementAst final : public StatementAst
{
public:
FString interfaceName;
FString structName;
String interfaceName;
String structName;
std::vector<ImplementMethod> methods;
ImplementAst()
{
type = AstType::ImplementSt;
}
ImplementAst() { type = AstType::ImplementSt; }
ImplementAst(FString _interfaceName, FString _structName, std::vector<ImplementMethod> _methods) :
ImplementAst(String _interfaceName, String _structName, std::vector<ImplementMethod> _methods) :
interfaceName(std::move(_interfaceName)), structName(std::move(_structName)), methods(std::move(_methods))
{
type = AstType::ImplementSt;
@@ -43,4 +40,4 @@ namespace Fig::Ast
};
using Implement = std::shared_ptr<ImplementAst>;
};
}; // namespace Fig::Ast

View File

@@ -14,17 +14,14 @@ namespace Fig::Ast
class ImportSt final : public StatementAst
{
public:
std::vector<FString> path;
std::vector<FString> names;
std::vector<String> path;
std::vector<String> names;
FString rename;
String rename;
ImportSt()
{
type = AstType::ImportSt;
}
ImportSt() { type = AstType::ImportSt; }
ImportSt(std::vector<FString> _path, std::vector<FString> _names, const FString &_rename) :
ImportSt(std::vector<String> _path, std::vector<String> _names, const String &_rename) :
path(std::move(_path)), names(std::move(_names)), rename(_rename)
{
type = AstType::ImportSt;
@@ -32,4 +29,4 @@ namespace Fig::Ast
};
using Import = std::shared_ptr<ImportSt>;
};
}; // namespace Fig::Ast

View File

@@ -3,7 +3,6 @@
#include <Ast/functionParameters.hpp>
#include <Ast/astBase.hpp>
namespace Fig::Ast
{
/*
@@ -20,35 +19,28 @@ namespace Fig::Ast
*/
struct InterfaceMethod
{
FString name;
String name;
FunctionParameters paras;
Expression returnType;
BlockStatement defaultBody = nullptr; // nullptr is non-default func
bool hasDefaultBody() const
{
return defaultBody != nullptr;
}
bool hasDefaultBody() const { return defaultBody != nullptr; }
};
class InterfaceDefAst final : public StatementAst
{
public:
FString name;
String name;
std::vector<InterfaceMethod> methods;
std::vector<FString> parents; // Feature, NOT NOW
std::vector<String> parents; // Feature, NOT NOW
bool isPublic;
InterfaceDefAst()
{
type = AstType::InterfaceDefSt;
}
InterfaceDefAst() { type = AstType::InterfaceDefSt; }
InterfaceDefAst(FString _name, std::vector<InterfaceMethod> _methods, bool _isPublic) :
InterfaceDefAst(String _name, std::vector<InterfaceMethod> _methods, bool _isPublic) :
name(std::move(_name)), methods(std::move(_methods)), isPublic(_isPublic)
{
type = AstType::InterfaceDefSt;
@@ -56,4 +48,4 @@ namespace Fig::Ast
};
using InterfaceDef = std::shared_ptr<InterfaceDefAst>;
};
}; // namespace Fig::Ast

View File

@@ -11,13 +11,16 @@ namespace Fig::Ast
struct StructDefField
{
AccessModifier am;
FString fieldName;
String fieldName;
Expression declaredType;
Expression defaultValueExpr;
StructDefField() {}
StructDefField(AccessModifier _am, FString _fieldName, Expression _declaredType, Expression _defaultValueExpr) :
am(std::move(_am)), fieldName(std::move(_fieldName)), declaredType(std::move(_declaredType)), defaultValueExpr(std::move(_defaultValueExpr))
StructDefField(AccessModifier _am, String _fieldName, Expression _declaredType, Expression _defaultValueExpr) :
am(std::move(_am)),
fieldName(std::move(_fieldName)),
declaredType(std::move(_declaredType)),
defaultValueExpr(std::move(_defaultValueExpr))
{
}
};
@@ -25,15 +28,12 @@ namespace Fig::Ast
{
public:
bool isPublic;
const FString name;
const String name;
const std::vector<StructDefField> fields; // field name (:type name = default value expression)
// name / name: String / name: String = "Fig"
const BlockStatement body;
StructDefSt()
{
type = AstType::StructSt;
}
StructDefSt(bool _isPublic, FString _name, std::vector<StructDefField> _fields, BlockStatement _body) :
StructDefSt() { type = AstType::StructSt; }
StructDefSt(bool _isPublic, String _name, std::vector<StructDefField> _fields, BlockStatement _body) :
isPublic(std::move(_isPublic)), name(std::move(_name)), fields(std::move(_fields)), body(std::move(_body))
{
type = AstType::StructSt;
@@ -41,4 +41,4 @@ namespace Fig::Ast
};
using StructDef = std::shared_ptr<StructDefSt>;
}; // namespace Fig
}; // namespace Fig::Ast

View File

@@ -10,8 +10,8 @@ namespace Fig::Ast
public:
bool isPublic;
bool isConst;
FString name;
// FString typeName;
String name;
// String typeName;
Expression declaredType;
Expression expr;
@@ -24,7 +24,8 @@ namespace Fig::Ast
expr = nullptr;
followupType = false;
}
VarDefAst(bool _isPublic, bool _isConst, FString _name, Expression _declaredType, Expression _expr, bool _followupType)
VarDefAst(
bool _isPublic, bool _isConst, String _name, Expression _declaredType, Expression _expr, bool _followupType)
{
type = AstType::VarDefSt;
isPublic = _isPublic;
@@ -37,4 +38,4 @@ namespace Fig::Ast
};
using VarDef = std::shared_ptr<VarDefAst>;
} // namespace Fig
} // namespace Fig::Ast

View File

@@ -1,7 +1,7 @@
#pragma once
#include <Token/token.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <format>
#include <unordered_map>
@@ -66,43 +66,43 @@ namespace Fig::Ast
ThrowSt,
};
// static const std::unordered_map<AstType, FString> astTypeToString{
// static const std::unordered_map<AstType, String> astTypeToString{
// /* Base Class */
// {AstType::_AstBase, FString(u8"Ast")},
// {AstType::StatementBase, FString(u8"Statement")},
// {AstType::ExpressionBase, FString(u8"Expression")},
// {AstType::_AstBase, String(U"Ast")},
// {AstType::StatementBase, String(U"Statement")},
// {AstType::ExpressionBase, String(U"Expression")},
// /* Expression */
// {AstType::ValueExpr, FString(u8"ValueExpr")},
// {AstType::LambdaExpr, FString(u8"LambdaExpr")},
// {AstType::UnaryExpr, FString(u8"UnaryExpr")},
// {AstType::BinaryExpr, FString(u8"BinaryExpr")},
// {AstType::TernaryExpr, FString(u8"TernaryExpr")},
// {AstType::ValueExpr, String(U"ValueExpr")},
// {AstType::LambdaExpr, String(U"LambdaExpr")},
// {AstType::UnaryExpr, String(U"UnaryExpr")},
// {AstType::BinaryExpr, String(U"BinaryExpr")},
// {AstType::TernaryExpr, String(U"TernaryExpr")},
// {AstType::InitExpr, FString(u8"InitExpr")},
// {AstType::InitExpr, String(U"InitExpr")},
// /* Statement */
// {AstType::BlockStatement, FString(u8"BlockStatement")},
// {AstType::BlockStatement, String(U"BlockStatement")},
// {AstType::VarDefSt, FString(u8"VarSt")},
// {AstType::FunctionDefSt, FString(u8"FunctionDefSt")},
// {AstType::StructSt, FString(u8"StructSt")},
// {AstType::ImplementSt, FString(u8"ImplementSt")},
// {AstType::VarDefSt, String(U"VarSt")},
// {AstType::FunctionDefSt, String(U"FunctionDefSt")},
// {AstType::StructSt, String(U"StructSt")},
// {AstType::ImplementSt, String(U"ImplementSt")},
// {AstType::IfSt, FString(u8"IfSt")},
// {AstType::ElseSt, FString(u8"ElseSt")},
// {AstType::ElseIfSt, FString(u8"ElseIfSt")},
// {AstType::VarAssignSt, FString(u8"VarAssignSt")},
// {AstType::WhileSt, FString(u8"WhileSt")},
// {AstType::ReturnSt, FString(u8"ReturnSt")},
// {AstType::BreakSt, FString(u8"BreakSt")},
// {AstType::ContinueSt, FString(u8"ContinueSt")},
// {AstType::IfSt, String(U"IfSt")},
// {AstType::ElseSt, String(U"ElseSt")},
// {AstType::ElseIfSt, String(U"ElseIfSt")},
// {AstType::VarAssignSt, String(U"VarAssignSt")},
// {AstType::WhileSt, String(U"WhileSt")},
// {AstType::ReturnSt, String(U"ReturnSt")},
// {AstType::BreakSt, String(U"BreakSt")},
// {AstType::ContinueSt, String(U"ContinueSt")},
// };
struct AstAddressInfo
{
size_t line, column;
std::shared_ptr<FString> sourcePath;
std::shared_ptr<std::vector<FString>> sourceLines;
std::shared_ptr<String> sourcePath;
std::shared_ptr<std::vector<String>> sourceLines;
};
class _AstBase
@@ -122,13 +122,14 @@ namespace Fig::Ast
void setAAI(AstAddressInfo _aai) { aai = std::move(_aai); }
virtual FString typeName()
virtual String typeName()
{
return FString::fromStringView(FStringView::fromBasicStringView(magic_enum::enum_name(type)));
const auto &name = magic_enum::enum_name(type);
return String(std::string(name.data(), name.length()));
}
virtual FString toString()
virtual String toString()
{
return FString(std::format("<Base Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
return String(std::format("<Base Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
}
AstAddressInfo getAAI() { return aai; }
@@ -143,9 +144,9 @@ namespace Fig::Ast
using _AstBase::operator=;
StatementAst() { type = AstType::StatementBase; }
virtual FString toString() override
virtual String toString() override
{
return FString(std::format("<Stmt Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
return String(std::format("<Stmt Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
}
};
@@ -154,9 +155,9 @@ namespace Fig::Ast
public:
EofStmt() { type = AstType::StatementBase; }
virtual FString toString() override
virtual String toString() override
{
return FString(std::format("<EOF Stmt at {}:{}>", aai.line, aai.column));
return String(std::format("<EOF Stmt at {}:{}>", aai.line, aai.column));
}
};
@@ -167,9 +168,9 @@ namespace Fig::Ast
using _AstBase::operator=;
ExpressionAst() { type = AstType::ExpressionBase; }
virtual FString toString() override
virtual String toString() override
{
return FString(std::format("<Expr Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
return String(std::format("<Expr Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
}
};
enum class Operator : uint8_t
@@ -325,10 +326,10 @@ namespace Fig::Ast
std::vector<Statement> stmts;
BlockStatementAst() { type = AstType::BlockStatement; }
BlockStatementAst(std::vector<Statement> _stmts) : stmts(std::move(_stmts)) { type = AstType::BlockStatement; }
virtual FString typeName() override { return FString(u8"BlockStatement"); }
virtual FString toString() override
virtual String typeName() override { return String(U"BlockStatement"); }
virtual String toString() override
{
return FString(std::format("<StmtAst '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
return String(std::format("<StmtAst '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
}
virtual ~BlockStatementAst() = default;
};

View File

@@ -2,7 +2,7 @@
#include <Ast/astBase.hpp>
#include <Evaluator/Value/Type.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <format>
@@ -17,15 +17,15 @@ namespace Fig::Ast
func test2(dp1 = 10, dp2:String = "default parameter 2")
*/
using PosParasType = std::vector<std::pair<FString, Expression>>;
using PosParasType = std::vector<std::pair<String, Expression>>;
// name type exp
using DefParasType = std::vector<std::pair<FString, std::pair<Expression, Expression>>>;
using DefParasType = std::vector<std::pair<String, std::pair<Expression, Expression>>>;
// name type exp default value
PosParasType posParas;
DefParasType defParas; // default parameters
FString variadicPara;
String variadicPara;
bool variadic = false;
FunctionParameters()
@@ -36,7 +36,7 @@ namespace Fig::Ast
posParas = std::move(_posParas);
defParas = std::move(_defParas);
}
FunctionParameters(FString _variadicPara)
FunctionParameters(String _variadicPara)
{
variadicPara = std::move(_variadicPara);
variadic = true;
@@ -52,46 +52,46 @@ namespace Fig::Ast
return posParas == other.posParas && defParas == other.defParas && variadicPara == other.variadicPara && variadic == other.variadic;
}
FString toString() const
String toString() const
{
if (variadic)
{
return FString(variadicPara + u8"...");
return String(variadicPara + U"...");
}
const auto posParasToString = [this]() {
FString out;
String out;
for (auto &p : posParas)
{
out += p.first;
if (p.second != nullptr)
{
out += FString(u8":" + p.second->toString());
out += String(String(U":") + p.second->toString());
}
out += u8",";
out += U",";
}
out.pop_back();
return out;
};
const auto defParasToString = [this]() {
FString out;
String out;
for (auto &p : defParas)
{
out += p.first;
if (p.second.first != nullptr)
{
out += FString(u8":" + p.second.first->toString());
out += String(String(U":") + p.second.first->toString());
}
if (p.second.second != nullptr)
{
out += u8"=";
out += U"=";
out += p.second.second->toString();
}
out += u8",";
out += U",";
}
out.pop_back();
return out;
};
return FString(std::format("{},{}", posParasToString().toBasicString(), defParasToString().toBasicString()));
return String(std::format("{},{}", posParasToString().toBasicString(), defParasToString().toBasicString()));
}
};
} // namespace Fig::Ast

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Bytecode/Instruction.hpp>
#include <Evaluator/Value/value.hpp>
@@ -10,16 +10,16 @@ namespace Fig
{
struct ChunkAddressInfo
{
FString sourcePath;
std::vector<FString> sourceLines;
String sourcePath;
std::vector<String> sourceLines;
};
struct Chunk
{
Instructions ins; // vector<Instruction>
Instructions ins; // vector<Instruction>
std::vector<Object> constants; // 常量池
std::vector<InstructionAddressInfo> instructions_addr; // 下标和ins对齐表示每个Instruction对应的地址
ChunkAddressInfo addr; // 代码块独立Addr
ChunkAddressInfo addr; // 代码块独立Addr
};
};
}; // namespace Fig

View File

@@ -8,15 +8,15 @@ namespace Fig
{
using AddressableError::AddressableError;
virtual FString toString() const override
virtual String toString() const override
{
std::string msg = std::format("[CompileError] {} in [{}] {}",
this->message.toBasicString(),
this->src_loc.file_name(),
this->src_loc.function_name());
return FString(msg);
return String(msg);
}
virtual FString getErrorType() const override { return FString(u8"CompileError"); }
virtual String getErrorType() const override { return String(U"\1"); }
};
};
}; // namespace Fig

View File

@@ -7,15 +7,14 @@ namespace Fig
{
struct CompiledFunction
{
Chunk chunk; // 函数代码块
FString name; // 函数名
String name; // 函数名
uint64_t posArgCount; // 位置参数数量
uint64_t defArgCount; // 默认参数数量
bool variadicPara; // 可变参数(是:最后为可变,否:不可变)
uint64_t localCount; // 局部变量数量(不包括参数)
uint64_t slotCount; // = 总参数数量 + 局部变量数量
uint64_t localCount; // 局部变量数量(不包括参数)
uint64_t slotCount; // = 总参数数量 + 局部变量数量
};
};
}; // namespace Fig

View File

@@ -24,9 +24,9 @@ int main()
// ---------------- fib ----------------
Instructions fib_ins{
/* 0 */ {OpCode::LOAD_LOCAL, 0}, // x
/* 1 */ {OpCode::LOAD_CONST, 0}, // 1
/* 2 */ {OpCode::LTET}, // x <= 1
/* 0 */ {OpCode::LOAD_LOCAL, 0}, // x
/* 1 */ {OpCode::LOAD_CONST, 0}, // 1
/* 2 */ {OpCode::LTET}, // x <= 1
/* 3 */ {OpCode::JUMP_IF_FALSE, 2}, // false -> jump to 6
/* 4 */ {OpCode::LOAD_LOCAL, 0}, // return x
@@ -34,13 +34,13 @@ int main()
/* 6 */ {OpCode::LOAD_LOCAL, 0}, // x
/* 7 */ {OpCode::LOAD_CONST, 0}, // 1
/* 8 */ {OpCode::SUB}, // x - 1
/* 8 */ {OpCode::SUB}, // x - 1
/* 9 */ {OpCode::LOAD_CONST, 2}, // fib
/* 10 */ {OpCode::CALL, 1}, // fib(x-1)
/* 11 */ {OpCode::LOAD_LOCAL, 0}, // x
/* 12 */ {OpCode::LOAD_CONST, 1}, // 2
/* 13 */ {OpCode::SUB}, // x - 2
/* 13 */ {OpCode::SUB}, // x - 2
/* 14 */ {OpCode::LOAD_CONST, 2}, // fib
/* 15 */ {OpCode::CALL, 1}, // fib(x-2)
@@ -56,7 +56,7 @@ int main()
CompiledFunction fib_fn{
{},
u8"fib",
U"\1",
1, // posArgCount
0,
false,
@@ -81,13 +81,13 @@ int main()
};
std::vector<Object> main_consts{
Object((int64_t)251), // 0
Object(Function(&fib_fn)), // 1
Object((int64_t) 251), // 0
Object(Function(&fib_fn)), // 1
};
Chunk main_chunk{main_ins, main_consts, {}, ChunkAddressInfo{}};
CompiledFunction main_fn{main_chunk, u8"main", 0, 0, false, 0, 0};
CompiledFunction main_fn{main_chunk, U"\1", 0, 0, false, 0, 0};
CallFrame entry{.ip = 0, .base = 0, .fn = main_fn};

312
src/Core/CharUtils.hpp Normal file
View File

@@ -0,0 +1,312 @@
#pragma once
#include <cassert>
class CharUtils
{
public:
static bool isDigit(char32_t c) { return c >= U'0' && c <= U'9'; }
static bool isAlpha(char32_t c)
{
// ASCII字母
if ((c >= U'A' && c <= U'Z') || (c >= U'a' && c <= U'z')) return true;
// Unicode字母检查
// Ll - 小写字母
// Lu - 大写字母
// Lt - 标题字母
// Lm - 修饰字母
// Lo - 其他字母
// 基本拉丁字母
if ((c >= 0x00C0 && c <= 0x00D6) || // Latin-1 Supplement
(c >= 0x00D8 && c <= 0x00F6) || // Latin-1 Supplement
(c >= 0x00F8 && c <= 0x02AF) || // Latin Extended
(c >= 0x0370 && c <= 0x052F) || // Greek, Cyrillic
(c >= 0x0591 && c <= 0x05F4) || // Hebrew
(c >= 0x0600 && c <= 0x06FF) || // Arabic
(c >= 0x0700 && c <= 0x0D7F) || // Syriac, Thaana, Devanagari, etc.
(c >= 0x0E00 && c <= 0x0E7F) || // Thai
(c >= 0x0F00 && c <= 0x0FFF) || // Tibetan
(c >= 0x1000 && c <= 0x109F) || // Myanmar
(c >= 0x10A0 && c <= 0x10FF) || // Georgian
(c >= 0x1100 && c <= 0x11FF) || // Hangul Jamo
(c >= 0x1200 && c <= 0x137F) || // Ethiopic
(c >= 0x13A0 && c <= 0x13FF) || // Cherokee
(c >= 0x1400 && c <= 0x167F) || // Unified Canadian Aboriginal Syllabics
(c >= 0x1680 && c <= 0x169F) || // Ogham
(c >= 0x16A0 && c <= 0x16FF) || // Runic
(c >= 0x1700 && c <= 0x171F) || // Tagalog
(c >= 0x1720 && c <= 0x173F) || // Hanunoo
(c >= 0x1740 && c <= 0x175F) || // Buhid
(c >= 0x1760 && c <= 0x177F) || // Tagbanwa
(c >= 0x1780 && c <= 0x17FF) || // Khmer
(c >= 0x1800 && c <= 0x18AF) || // Mongolian
(c >= 0x1900 && c <= 0x194F) || // Limbu
(c >= 0x1950 && c <= 0x197F) || // Tai Le
(c >= 0x19E0 && c <= 0x19FF) || // Khmer Symbols
(c >= 0x1D00 && c <= 0x1D7F) || // Phonetic Extensions
(c >= 0x1E00 && c <= 0x1EFF) || // Latin Extended Additional
(c >= 0x1F00 && c <= 0x1FFF) || // Greek Extended
(c >= 0x2C00 && c <= 0x2C5F) || // Glagolitic
(c >= 0x2C60 && c <= 0x2C7F) || // Latin Extended-C
(c >= 0x2C80 && c <= 0x2CFF) || // Coptic
(c >= 0x2D00 && c <= 0x2D2F) || // Georgian Supplement
(c >= 0x2D30 && c <= 0x2D7F) || // Tifinagh
(c >= 0x2D80 && c <= 0x2DDF) || // Ethiopic Extended
(c >= 0x2DE0 && c <= 0x2DFF) || // Cyrillic Extended-A
(c >= 0x2E00 && c <= 0x2E7F) || // Supplemental Punctuation
(c >= 0xA640 && c <= 0xA69F) || // Cyrillic Extended-B
(c >= 0xA720 && c <= 0xA7FF) || // Latin Extended-D
(c >= 0xA800 && c <= 0xA82F) || // Syloti Nagri
(c >= 0xA840 && c <= 0xA87F) || // Phags-pa
(c >= 0xAC00 && c <= 0xD7AF) || // Hangul Syllables
(c >= 0xF900 && c <= 0xFAFF) || // CJK Compatibility Ideographs
(c >= 0xFB00 && c <= 0xFB4F) || // Alphabetic Presentation Forms
(c >= 0xFE20 && c <= 0xFE2F) || // Combining Half Marks
(c >= 0xFE70 && c <= 0xFEFF) || // Arabic Presentation Forms-B
(c >= 0xFF00 && c <= 0xFFEF) || // Halfwidth and Fullwidth Forms
(c >= 0x10000 && c <= 0x100FF) || // Linear B Syllabary
(c >= 0x10140 && c <= 0x1018F) || // Ancient Greek Numbers
(c >= 0x10300 && c <= 0x1032F) || // Old Italic
(c >= 0x10330 && c <= 0x1034F) || // Gothic
(c >= 0x10380 && c <= 0x1039F) || // Ugaritic
(c >= 0x103A0 && c <= 0x103DF) || // Old Persian
(c >= 0x10400 && c <= 0x1044F) || // Deseret
(c >= 0x10450 && c <= 0x1047F) || // Shavian
(c >= 0x10480 && c <= 0x104AF) || // Osmanya
(c >= 0x10800 && c <= 0x1083F) || // Cypriot Syllabary
(c >= 0x10900 && c <= 0x1091F) || // Phoenician
(c >= 0x10A00 && c <= 0x10A5F) || // Kharoshthi
(c >= 0x12000 && c <= 0x123FF) || // Cuneiform
(c >= 0x1D400 && c <= 0x1D7FF) || // Mathematical Alphanumeric Symbols
(c >= 0x1F130 && c <= 0x1F1FF) || // Enclosed Alphanumeric Supplement
(c >= 0x20000 && c <= 0x2A6DF) || // CJK Unified Ideographs Extension B
(c >= 0x2A700 && c <= 0x2B73F) || // CJK Unified Ideographs Extension C
(c >= 0x2B740 && c <= 0x2B81F) || // CJK Unified Ideographs Extension D
(c >= 0x2F800 && c <= 0x2FA1F)) // CJK Compatibility Ideographs Supplement
{
return true;
}
// CJK统一表意文字 (中文、日文、韩文)
if ((c >= 0x4E00 && c <= 0x9FFF) || // CJK Unified Ideographs
(c >= 0x3400 && c <= 0x4DBF) || // CJK Unified Ideographs Extension A
(c >= 0x2E80 && c <= 0x2EFF) || // CJK Radicals Supplement
(c >= 0x2F00 && c <= 0x2FDF) || // Kangxi Radicals
(c >= 0x2FF0 && c <= 0x2FFF) || // Ideographic Description Characters
(c >= 0x3000 && c <= 0x303F) || // CJK Symbols and Punctuation
(c >= 0x31C0 && c <= 0x31EF) || // CJK Strokes
(c >= 0x3200 && c <= 0x32FF) || // Enclosed CJK Letters and Months
(c >= 0x3300 && c <= 0x33FF) || // CJK Compatibility
(c >= 0xF900 && c <= 0xFAFF) || // CJK Compatibility Ideographs
(c >= 0xFE30 && c <= 0xFE4F) || // CJK Compatibility Forms
(c >= 0x1F200 && c <= 0x1F2FF)) // Enclosed Ideographic Supplement
{
return true;
}
return false;
}
static bool isUpper(char32_t c)
{
// ASCII大写字母
if (c >= U'A' && c <= U'Z') return true;
// Unicode大写字母检查
if ((c >= 0x00C0 && c <= 0x00D6) || // Latin-1 Supplement
(c >= 0x00D8 && c <= 0x00DE) || // Latin-1 Supplement
(c >= 0x0100 && c <= 0x012E) || // Latin Extended-A
(c >= 0x0132 && c <= 0x0136) || (c >= 0x0139 && c <= 0x0147) || (c >= 0x014A && c <= 0x0178)
|| (c >= 0x0179 && c <= 0x017D) || (c >= 0x0181 && c <= 0x0182) || c == 0x0186 || c == 0x0189 || c == 0x018A
|| c == 0x018E || c == 0x018F || c == 0x0190 || c == 0x0191 || c == 0x0193 || c == 0x0194 || c == 0x0196
|| c == 0x0197 || c == 0x0198 || c == 0x019C || c == 0x019D || c == 0x019F || c == 0x01A0 || c == 0x01A2
|| c == 0x01A4 || c == 0x01A7 || c == 0x01A9 || c == 0x01AC || c == 0x01AE || c == 0x01AF
|| (c >= 0x01B1 && c <= 0x01B3) || c == 0x01B5 || c == 0x01B7 || c == 0x01B8 || c == 0x01BC || c == 0x01C4
|| c == 0x01C7 || c == 0x01CA || c == 0x01CD || c == 0x01CF || c == 0x01D1 || c == 0x01D3 || c == 0x01D5
|| c == 0x01D7 || c == 0x01D9 || c == 0x01DB || c == 0x01DE || c == 0x01E0 || c == 0x01E2 || c == 0x01E4
|| c == 0x01E6 || c == 0x01E8 || c == 0x01EA || c == 0x01EC || c == 0x01EE || c == 0x01F4 || c == 0x01FA
|| (c >= 0x01FC && c <= 0x01FF) || (c >= 0x0200 && c <= 0x0220) || (c >= 0x0222 && c <= 0x0232)
|| (c >= 0x0370 && c <= 0x0373) || (c >= 0x0376 && c <= 0x0377) || (c >= 0x03D8 && c <= 0x03EF)
|| (c >= 0x03F4 && c <= 0x03F7) || (c >= 0x03F9 && c <= 0x03FA) || (c >= 0x03FD && c <= 0x042F)
|| (c >= 0x0460 && c <= 0x0480) || (c >= 0x048A && c <= 0x04C0) || (c >= 0x04C1 && c <= 0x04CD)
|| (c >= 0x04D0 && c <= 0x0528) || (c >= 0x0531 && c <= 0x0556) || (c >= 0x10A0 && c <= 0x10C5)
|| (c >= 0x1E00 && c <= 0x1E94) || (c >= 0x1EA0 && c <= 0x1EFE) || (c >= 0x2C00 && c <= 0x2C2E)
|| (c >= 0x2C60 && c <= 0x2C62) || (c >= 0xA640 && c <= 0xA66C) || (c >= 0xA680 && c <= 0xA69A)
|| (c >= 0xA722 && c <= 0xA72E) || (c >= 0xA732 && c <= 0xA76E) || (c >= 0xA779 && c <= 0xA77D)
|| (c >= 0xA77E && c <= 0xA786) || (c >= 0xA78B && c <= 0xA78D) || (c >= 0xA790 && c <= 0xA792)
|| (c >= 0xA796 && c <= 0xA7A8) || (c >= 0xA7AA && c <= 0xA7AE) || (c >= 0xA7B0 && c <= 0xA7B4)
|| (c >= 0xA7B6 && c <= 0xA7BE) || (c >= 0xFF21 && c <= 0xFF3A) || // 全角大写字母
(c >= 0x10400 && c <= 0x10427) || // Deseret
(c >= 0x104B0 && c <= 0x104D3) || // Osage
(c >= 0x10C80 && c <= 0x10CB2) || // Old Hungarian
(c >= 0x118A0 && c <= 0x118DF) || // Warang Citi
(c >= 0x1D400 && c <= 0x1D419) || // Mathematical bold capital
(c >= 0x1D434 && c <= 0x1D44D) || // Mathematical italic capital
(c >= 0x1D468 && c <= 0x1D481) || // Mathematical bold italic capital
(c >= 0x1D49C && c <= 0x1D4B5) || // Mathematical script capital
(c >= 0x1D4D0 && c <= 0x1D4E9) || // Mathematical bold script capital
(c >= 0x1D504 && c <= 0x1D51C) || // Mathematical fraktur capital
(c >= 0x1D538 && c <= 0x1D550) || // Mathematical double-struck capital
(c >= 0x1D56C && c <= 0x1D585) || // Mathematical bold fraktur capital
(c >= 0x1D5A0 && c <= 0x1D5B9) || // Mathematical sans-serif capital
(c >= 0x1D5D4 && c <= 0x1D5ED) || // Mathematical sans-serif bold capital
(c >= 0x1D608 && c <= 0x1D621) || // Mathematical sans-serif italic capital
(c >= 0x1D63C && c <= 0x1D655) || // Mathematical sans-serif bold italic capital
(c >= 0x1D670 && c <= 0x1D689) || // Mathematical monospace capital
(c >= 0x1D6A8 && c <= 0x1D6C0) || // Mathematical bold capital Greek
(c >= 0x1D6E2 && c <= 0x1D6FA) || // Mathematical italic capital Greek
(c >= 0x1D71C && c <= 0x1D734) || // Mathematical bold italic capital Greek
(c >= 0x1D756 && c <= 0x1D76E) || // Mathematical sans-serif bold capital Greek
(c >= 0x1D790 && c <= 0x1D7A8)) // Mathematical sans-serif bold italic capital Greek
{
return true;
}
return false;
}
static bool isLower(char32_t c)
{
// ASCII小写字母
if (c >= U'a' && c <= U'z') return true;
// Unicode小写字母检查
if ((c >= 0x00DF && c <= 0x00F6) || // Latin-1 Supplement
(c >= 0x00F8 && c <= 0x00FF) || // Latin-1 Supplement
(c >= 0x0101 && c <= 0x012F) || // Latin Extended-A
(c >= 0x0133 && c <= 0x0137) || (c >= 0x013A && c <= 0x0148) || (c >= 0x014B && c <= 0x0177)
|| (c >= 0x017A && c <= 0x017E) || (c >= 0x0183 && c <= 0x0185) || c == 0x0188 || c == 0x018C || c == 0x0192
|| c == 0x0195 || c == 0x0199 || c == 0x019A || c == 0x019E || c == 0x01A1 || c == 0x01A3 || c == 0x01A5
|| c == 0x01A8 || c == 0x01AA || c == 0x01AB || c == 0x01AD || c == 0x01B0 || c == 0x01B4 || c == 0x01B6
|| c == 0x01B9 || c == 0x01BA || c == 0x01BD || c == 0x01C6 || c == 0x01C9 || c == 0x01CC || c == 0x01CE
|| c == 0x01D0 || c == 0x01D2 || c == 0x01D4 || c == 0x01D6 || c == 0x01D8 || c == 0x01DA || c == 0x01DC
|| c == 0x01DD || c == 0x01DF || c == 0x01E1 || c == 0x01E3 || c == 0x01E5 || c == 0x01E7 || c == 0x01E9
|| c == 0x01EB || c == 0x01ED || c == 0x01F3 || c == 0x01F5 || c == 0x01FB || (c >= 0x0201 && c <= 0x0217)
|| (c >= 0x0250 && c <= 0x02A8) || (c >= 0x03B1 && c <= 0x03C1) || (c >= 0x03C3 && c <= 0x03CE)
|| (c >= 0x0430 && c <= 0x044F) || (c >= 0x0451 && c <= 0x045C) || (c >= 0x045E && c <= 0x0481)
|| (c >= 0x0491 && c <= 0x04BF) || (c >= 0x04C2 && c <= 0x04CE) || (c >= 0x04D1 && c <= 0x0527)
|| (c >= 0x0561 && c <= 0x0587) || (c >= 0x1D00 && c <= 0x1D2B) || (c >= 0x1D62 && c <= 0x1D77)
|| (c >= 0x1D79 && c <= 0x1D9A) || (c >= 0x1E01 && c <= 0x1E95) || (c >= 0x1EA1 && c <= 0x1EFF)
|| (c >= 0x2C30 && c <= 0x2C5E) || (c >= 0x2C61 && c <= 0x2C65) || (c >= 0x2C66 && c <= 0x2C6C)
|| (c >= 0x2C73 && c <= 0x2C74) || (c >= 0x2C76 && c <= 0x2C7B) || (c >= 0xA641 && c <= 0xA66D)
|| (c >= 0xA681 && c <= 0xA69B) || (c >= 0xA723 && c <= 0xA72F) || (c >= 0xA733 && c <= 0xA76F)
|| (c >= 0xA77A && c <= 0xA77C) || (c >= 0xA77F && c <= 0xA787) || (c >= 0xA78C && c <= 0xA78E)
|| (c >= 0xA791 && c <= 0xA793) || (c >= 0xA797 && c <= 0xA7A9) || (c >= 0xA7AB && c <= 0xA7AE)
|| (c >= 0xA7B1 && c <= 0xA7B5) || (c >= 0xA7B7 && c <= 0xA7BF) || (c >= 0xAB30 && c <= 0xAB5A)
|| (c >= 0xAB60 && c <= 0xAB65) || (c >= 0xAB70 && c <= 0xABBF) || (c >= 0xFB00 && c <= 0xFB06)
|| (c >= 0xFB13 && c <= 0xFB17) || (c >= 0xFF41 && c <= 0xFF5A) || // 全角小写字母
(c >= 0x10428 && c <= 0x1044F) || // Deseret lowercase
(c >= 0x104D8 && c <= 0x104FB) || // Osage lowercase
(c >= 0x10CC0 && c <= 0x10CF2) || // Old Hungarian lowercase
(c >= 0x118C0 && c <= 0x118E0) || // Warang Citi lowercase
(c >= 0x1D41A && c <= 0x1D433) || // Mathematical bold lowercase
(c >= 0x1D44E && c <= 0x1D467) || // Mathematical italic lowercase
(c >= 0x1D482 && c <= 0x1D49B) || // Mathematical bold italic lowercase
(c >= 0x1D4B6 && c <= 0x1D4CF) || // Mathematical script lowercase
(c >= 0x1D4EA && c <= 0x1D503) || // Mathematical bold script lowercase
(c >= 0x1D51E && c <= 0x1D537) || // Mathematical fraktur lowercase
(c >= 0x1D552 && c <= 0x1D56B) || // Mathematical double-struck lowercase
(c >= 0x1D586 && c <= 0x1D59F) || // Mathematical bold fraktur lowercase
(c >= 0x1D5BA && c <= 0x1D5D3) || // Mathematical sans-serif lowercase
(c >= 0x1D5EE && c <= 0x1D607) || // Mathematical sans-serif bold lowercase
(c >= 0x1D622 && c <= 0x1D63B) || // Mathematical sans-serif italic lowercase
(c >= 0x1D656 && c <= 0x1D66F) || // Mathematical sans-serif bold italic lowercase
(c >= 0x1D68A && c <= 0x1D6A5) || // Mathematical monospace lowercase
(c >= 0x1D6C1 && c <= 0x1D6DA) || // Mathematical bold lowercase Greek
(c >= 0x1D6FB && c <= 0x1D714) || // Mathematical italic lowercase Greek
(c >= 0x1D735 && c <= 0x1D74E) || // Mathematical bold italic lowercase Greek
(c >= 0x1D76F && c <= 0x1D788) || // Mathematical sans-serif bold lowercase Greek
(c >= 0x1D7A9 && c <= 0x1D7C2)) // Mathematical sans-serif bold italic lowercase Greek
{
return true;
}
return false;
}
static bool isAlnum(char32_t c) { return isAlpha(c) || isDigit(c); }
static bool isXdigit(char32_t c)
{
return isDigit(c) || (c >= U'a' && c <= U'f') || (c >= U'A' && c <= U'F') || (c >= 0xFF10 && c <= 0xFF19)
|| // 全角数字
(c >= 0xFF21 && c <= 0xFF26) || // 全角大写A-F
(c >= 0xFF41 && c <= 0xFF46); // 全角小写a-f
}
static bool isSpace(char32_t c)
{
return c == U' ' || c == U'\t' || c == U'\n' || c == U'\r' || c == U'\f' || c == U'\v' || c == 0x00A0
|| c == 0x1680 || c == 0x2000 || c == 0x2001 || c == 0x2002 || c == 0x2003 || c == 0x2004 || c == 0x2005
|| c == 0x2006 || c == 0x2007 || c == 0x2008 || c == 0x2009 || c == 0x200A || c == 0x202F || c == 0x205F
|| c == 0x3000;
}
static bool isCntrl(char32_t c) { return (c <= 0x1F) || (c >= 0x7F && c <= 0x9F) || c == 0x2028 || c == 0x2029; }
static bool isGraph(char32_t c) { return !isSpace(c) && !isCntrl(c) && c != 0x00AD && c != 0x180E; }
static bool isPrint(char32_t c) { return isGraph(c) || isSpace(c); }
static bool isPunct(char32_t c) { return isGraph(c) && !isAlnum(c); }
// 大小写转换
static char32_t toLower(char32_t c)
{
if (isLower(c)) return c;
if (c >= U'A' && c <= U'Z') return c + 32;
if (c >= 0xC0 && c <= 0xD6 && c != 0xD7) return c + 32;
if (c >= 0xD8 && c <= 0xDE) return c + 32;
assert(false && "Unsupported yet");
return c;
}
static char32_t toUpper(char32_t c)
{
if (isUpper(c)) return c;
if (c >= U'a' && c <= U'z') return c - 32;
if (c >= 0xE0 && c <= 0xF6 && c != 0xF7) return c - 32;
if (c >= 0xF8 && c <= 0xFE) return c - 32;
assert(false && "Unsupported yet");
return c;
}
// 检查是否是空白字符
static bool isWhitespace(char32_t c)
{
return c == U' ' || c == U'\t' || c == U'\n' || c == U'\r' || c == U'\f' || c == U'\v' || c == 0x00A0
|| c == 0x1680 || c == 0x2000 || c == 0x2001 || c == 0x2002 || c == 0x2003 || c == 0x2004 || c == 0x2005
|| c == 0x2006 || c == 0x2007 || c == 0x2008 || c == 0x2009 || c == 0x200A || c == 0x2028 || c == 0x2029
|| c == 0x202F || c == 0x205F || c == 0x3000;
}
// 检查是否是标点符号
static bool isPunctuation(char32_t c)
{
return (c >= 0x21 && c <= 0x2F) || (c >= 0x3A && c <= 0x40) || (c >= 0x5B && c <= 0x60)
|| (c >= 0x7B && c <= 0x7E) || (c >= 0x2000 && c <= 0x206F) || (c >= 0x2E00 && c <= 0x2E7F)
|| (c >= 0x3000 && c <= 0x303F) || (c >= 0xFE10 && c <= 0xFE1F) || (c >= 0xFE30 && c <= 0xFE4F)
|| (c >= 0xFF00 && c <= 0xFF0F) || (c >= 0xFF1A && c <= 0xFF20) || (c >= 0xFF3B && c <= 0xFF40)
|| (c >= 0xFF5B && c <= 0xFF65);
}
// 检查是否是表情符号
static bool isEmoji(char32_t c)
{
return (c >= 0x1F600 && c <= 0x1F64F) || // Emoticons
(c >= 0x1F300 && c <= 0x1F5FF) || // Miscellaneous Symbols and Pictographs
(c >= 0x1F680 && c <= 0x1F6FF) || // Transport and Map Symbols
(c >= 0x1F900 && c <= 0x1F9FF) || // Supplemental Symbols and Pictographs
(c >= 0x2600 && c <= 0x26FF) || // Miscellaneous Symbols
(c >= 0x2700 && c <= 0x27BF) || // Dingbats
(c >= 0xFE00 && c <= 0xFE0F) || // Variation Selectors
(c >= 0x1F1E6 && c <= 0x1F1FF) || // Regional Indicator Symbols
(c >= 0xE0020 && c <= 0xE007F); // Tags
}
};

12
src/Core/String.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include <Core/String.hpp>
namespace Fig::StringClass::DynamicCapacity
{
char32_t Iterator::operator*() const
{
if (str->is_ascii)
return str->is_heap ? str->heap.ascii[index] : str->sso.ascii[index];
else
return str->is_heap ? str->heap.utf32[index] : str->sso.utf32[index];
}
};

2052
src/Core/String.hpp Normal file

File diff suppressed because it is too large Load Diff

68
src/Core/StringTest.cpp Normal file
View File

@@ -0,0 +1,68 @@
#include <iostream>
#include <unordered_map>
#include "String.hpp"
using namespace Fig::StringClass::DynamicCapacity;
int main()
{
std::cout << "=== String Test ===\n";
// 1. 构造
String s1("Hello");
String s2("World");
String s3(U"你好世界"); // UTF-8中文
std::cout << "s1: " << s1.toBasicString() << "\n";
std::cout << "s2: " << s2.toBasicString() << "\n";
std::cout << "s3: " << s3.toBasicString() << "\n";
// 2. operator+
String s4 = s1 + String(", ") + s2;
std::cout << "s4 (s1 + ', ' + s2): " << s4.toBasicString() << "\n";
// 3. operator+=
s1 += String("!!!");
std::cout << "s1 after += '!!!': " << s1.toBasicString() << "\n";
// 4. operator==
std::cout << "s1 == 'Hello!!!'? " << (s1 == String("Hello!!!") ? "true" : "false") << "\n";
std::cout << "s1 == s2? " << (s1 == s2 ? "true" : "false") << "\n";
// 5. set / at / operator[]
s2.set(0, 'w'); // 'World' -> 'world'
std::cout << "s2 after set(0,'w'): " << s2.toBasicString() << "\n";
std::cout << "s2.at(1): " << String(s2.at(1)).toBasicString() << "\n";
std::cout << "s2[2]: " << String(s2[2]).toBasicString() << "\n";
// 6. reverse
s1.reverse();
std::cout << "s1 reversed: " << s1.toBasicString() << "\n";
// 7. clear
s3.clear();
std::cout << "s3 cleared, empty? " << (s3.empty() ? "true" : "false") << "\n";
// 8. reserve & shrink_to_fit
s4.reserve(100);
std::cout << "s4 reserved 100, length: " << s4.length() << "\n";
s4.shrink_to_fit();
std::cout << "s4 shrink_to_fit done, length: " << s4.length() << "\n";
// 9. reverse UTF-8 string
String utf8Str(U"🌟🚀"); // emoji
std::cout << "utf8Str: " << utf8Str.toBasicString() << "\n";
utf8Str.reverse();
std::cout << "utf8Str reversed: " << utf8Str.toBasicString() << "\n";
// 10. STL
std::unordered_map<String, String> map = {
{String("我去"), String("123")}
};
std::cout << map[String("我去")];
return 0;
}

View File

@@ -18,15 +18,9 @@ namespace Fig
return FStringView(reinterpret_cast<const char8_t *>(sv.data()));
}
explicit FStringView(std::string_view sv)
{
*this = fromBasicStringView(sv);
}
explicit FStringView(std::string_view sv) { *this = fromBasicStringView(sv); }
explicit FStringView()
{
*this = fromBasicStringView(std::string_view(""));
}
explicit FStringView() { *this = fromBasicStringView(std::string_view("")); }
std::string_view toBasicStringView() const
{
@@ -34,56 +28,26 @@ namespace Fig
}
};
class FString : public std::u8string
class String : public std::u8string
{
public:
using std::u8string::u8string;
using std::u8string::operator=;
FString operator+(const FString &x)
{
return FString(toBasicString() + x.toBasicString());
}
FString operator+(const char8_t *c)
{
return FString(*this + std::u8string(c));
}
String operator+(const String &x) { return String(toBasicString() + x.toBasicString()); }
String operator+(const char8_t *c) { return String(*this + std::u8string(c)); }
explicit FString(const std::u8string &str)
{
*this = fromU8String(str);
}
explicit FString(std::string str)
{
*this = fromBasicString(str);
}
explicit FString(FStringView sv)
{
*this = fromStringView(sv);
}
std::string toBasicString() const
{
return std::string(this->begin(), this->end());
}
FStringView toStringView() const
{
return FStringView(this->data(), this->size());
}
explicit String(const std::u8string &str) { *this = fromU8String(str); }
explicit String(std::string str) { *this = fromBasicString(str); }
explicit String(FStringView sv) { *this = fromStringView(sv); }
std::string toBasicString() const { return std::string(this->begin(), this->end()); }
FStringView toStringView() const { return FStringView(this->data(), this->size()); }
static FString fromBasicString(const std::string &str)
{
return FString(str.begin(), str.end());
}
static String fromBasicString(const std::string &str) { return String(str.begin(), str.end()); }
static FString fromStringView(FStringView sv)
{
return FString(reinterpret_cast<const char *>(sv.data()));
}
static String fromStringView(FStringView sv) { return String(reinterpret_cast<const char *>(sv.data())); }
static FString fromU8String(const std::u8string &str)
{
return FString(str.begin(), str.end());
}
static String fromU8String(const std::u8string &str) { return String(str.begin(), str.end()); }
size_t length() const
{
@@ -91,17 +55,14 @@ namespace Fig
size_t len = 0;
for (auto it = this->begin(); it != this->end(); ++it)
{
if ((*it & 0xC0) != 0x80)
{
++len;
}
if ((*it & 0xC0) != 0x80) { ++len; }
}
return len;
}
FString getRealChar(size_t index)
String getRealChar(size_t index)
{
FString ch;
String ch;
size_t cnt = 0;
for (size_t i = 0; i < size();)
{
@@ -112,13 +73,9 @@ namespace Fig
cplen = 3;
else if ((at(i) & 0xe0) == 0xc0)
cplen = 2;
if (i + cplen > size())
cplen = 1;
if (i + cplen > size()) cplen = 1;
if (cnt == index)
{
ch += substr(i, cplen);
}
if (cnt == index) { ch += substr(i, cplen); }
i += cplen;
++cnt;
@@ -127,7 +84,7 @@ namespace Fig
return ch;
}
void realReplace(size_t index, const FString &src)
void realReplace(size_t index, const String &src)
{
size_t cnt = 0;
for (size_t i = 0; i < size();)
@@ -139,13 +96,9 @@ namespace Fig
cplen = 3;
else if ((at(i) & 0xe0) == 0xc0)
cplen = 2;
if (i + cplen > size())
cplen = 1;
if (i + cplen > size()) cplen = 1;
if (cnt == index)
{
*this = FString(substr(0, i)) + src + FString(substr(i + cplen));
}
if (cnt == index) { *this = String(substr(0, i)) + src + String(substr(i + cplen)); }
i += cplen;
++cnt;
@@ -165,32 +118,22 @@ namespace Fig
cplen = 3;
else if ((at(i) & 0xe0) == 0xc0)
cplen = 2;
if (i + cplen > size())
cplen = 1;
if (i + cplen > size()) cplen = 1;
i += cplen;
++cnt;
if (cnt == index)
{
eraseStart = i;
}
if (cnt < index + n)
{
eraseCplens += cplen;
}
if (cnt == index) { eraseStart = i; }
if (cnt < index + n) { eraseCplens += cplen; }
}
erase(eraseStart, eraseCplens);
}
void realInsert(size_t index, const FString &src)
void realInsert(size_t index, const String &src)
{
if (index == length())
{
for (auto &c : src)
{
push_back(c);
}
for (auto &c : src) { push_back(c); }
return;
}
size_t cnt = 0;
@@ -203,13 +146,9 @@ namespace Fig
cplen = 3;
else if ((at(i) & 0xe0) == 0xc0)
cplen = 2;
if (i + cplen > size())
cplen = 1;
if (i + cplen > size()) cplen = 1;
if (cnt == index)
{
insert(i, src);
}
if (cnt == index) { insert(i, src); }
i += cplen;
++cnt;
@@ -222,9 +161,9 @@ namespace Fig
namespace std
{
template <>
struct hash<Fig::FString>
struct hash<Fig::String>
{
std::size_t operator()(const Fig::FString &s) const
std::size_t operator()(const Fig::String &s) const
{
return std::hash<std::u8string>{}(static_cast<const std::u8string &>(s));
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <cstdint>
#include <string_view>
@@ -54,6 +54,5 @@ namespace Fig
inline constexpr std::string_view COMPILER = __FCORE_COMPILER;
inline constexpr std::string_view COMPILE_TIME = __FCORE_COMPILE_TIME;
inline constexpr std::string_view ARCH = __FCORE_ARCH;
inline constexpr FString MAIN_FUNCTION = u8"main";
}; // namespace Core
}; // namespace Fig

View File

@@ -2,8 +2,8 @@
namespace Fig
{
const std::unordered_map<std::size_t, FString> Warning::standardWarnings = {
{1, FString(u8"Identifier is too similar to a keyword or a primitive type")},
{2, FString(u8"The identifier is too abstract")}
const std::unordered_map<std::size_t, String> Warning::standardWarnings = {
{1, String(U"Identifier is too similar to a keyword or a primitive type")},
{2, String(U"The identifier is too abstract")}
};
};

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Utils/magic_enum/magic_enum.hpp>
#include <unordered_map>
@@ -11,16 +11,17 @@ namespace Fig
{
private:
size_t id; // the id (standard) of warning
FString msg;
String msg;
size_t line, column;
public:
static const std::unordered_map<size_t, FString> standardWarnings;
Warning(size_t _id, FString _msg)
static const std::unordered_map<size_t, String> standardWarnings;
Warning(size_t _id, String _msg)
{
id = _id;
msg = std::move(_msg);
}
Warning(size_t _id, FString _msg, size_t _line, size_t _column)
Warning(size_t _id, String _msg, size_t _line, size_t _column)
{
id = _id;
msg = std::move(_msg);
@@ -28,28 +29,12 @@ namespace Fig
column = _column;
}
auto getIDName()
{
return standardWarnings.at(id);
}
auto getID()
{
return id;
}
auto getMsg()
{
return msg;
}
auto getLine()
{
return line;
}
auto getColumn()
{
return column;
}
auto getIDName() { return standardWarnings.at(id); }
auto getID() { return id; }
auto getMsg() { return msg; }
auto getLine() { return line; }
auto getColumn() { return column; }
};
};
}; // namespace Fig

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <exception>
#include <format>
@@ -14,20 +14,29 @@ namespace Fig
{
public:
explicit AddressableError() {}
explicit AddressableError(FString _msg,
explicit AddressableError(String _msg,
size_t _line,
size_t _column,
FString _sourcePath,
std::vector<FString> _sourceLines,
String _sourcePath,
std::vector<String> _sourceLines,
std::source_location loc = std::source_location::current()) :
src_loc(loc), line(_line), column(_column), sourcePath(std::move(_sourcePath)), sourceLines(std::move(_sourceLines))
src_loc(loc),
line(_line),
column(_column),
sourcePath(std::move(_sourcePath)),
sourceLines(std::move(_sourceLines))
{
message = _msg;
}
virtual FString toString() const
virtual String toString() const
{
std::string msg = std::format("[AddressableError] {} at {}:{}, in [{}] {}", std::string(this->message.begin(), this->message.end()), this->line, this->column, this->src_loc.file_name(), this->src_loc.function_name());
return FString(msg);
std::string msg = std::format("[AddressableError] {} at {}:{}, in [{}] {}",
this->message.toBasicString(),
this->line,
this->column,
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
}
const char *what() const noexcept override
{
@@ -38,37 +47,36 @@ namespace Fig
virtual size_t getLine() const { return line; }
virtual size_t getColumn() const { return column; }
FString getMessage() const { return message; }
FString getSourcePath() const { return sourcePath; }
std::vector<FString> getSourceLines() const { return sourceLines; }
String getMessage() const { return message; }
String getSourcePath() const { return sourcePath; }
std::vector<String> getSourceLines() const { return sourceLines; }
virtual FString getErrorType() const
{
return FString(u8"AddressableError");
}
virtual String getErrorType() const { return String(U"\1"); }
protected:
size_t line, column;
FString message;
String message;
FString sourcePath;
std::vector<FString> sourceLines;
String sourcePath;
std::vector<String> sourceLines;
};
class UnaddressableError : public std::exception
{
public:
explicit UnaddressableError() {}
explicit UnaddressableError(FString _msg,
std::source_location loc = std::source_location::current()) :
explicit UnaddressableError(String _msg, std::source_location loc = std::source_location::current()) :
src_loc(loc)
{
message = _msg;
}
virtual FString toString() const
virtual String toString() const
{
std::string msg = std::format("[UnaddressableError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name());
return FString(msg);
std::string msg = std::format("[UnaddressableError] {} in [{}] {}",
this->message.toBasicString(),
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
}
const char *what() const noexcept override
{
@@ -76,15 +84,12 @@ namespace Fig
return msg.c_str();
}
std::source_location src_loc;
FString getMessage() const { return message; }
String getMessage() const { return message; }
virtual FString getErrorType() const
{
return FString(u8"UnaddressableError");
}
virtual String getErrorType() const { return String(U"\1"); }
protected:
FString message;
String message;
};
class SyntaxError : public AddressableError
@@ -92,37 +97,36 @@ namespace Fig
public:
using AddressableError::AddressableError;
virtual FString toString() const override
virtual String toString() const override
{
std::string msg = std::format("[SyntaxError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name());
return FString(msg);
std::string msg = std::format("[SyntaxError] {} in [{}] {}",
this->message.toBasicString(),
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
}
virtual FString getErrorType() const override
{
return FString(u8"SyntaxError");
}
virtual String getErrorType() const override { return String(U"\1"); }
};
class RuntimeError final : public UnaddressableError
{
public:
using UnaddressableError::UnaddressableError;
explicit RuntimeError(FString _msg,
std::source_location loc = std::source_location::current()) :
explicit RuntimeError(String _msg, std::source_location loc = std::source_location::current()) :
UnaddressableError(_msg, loc)
{
}
virtual FString toString() const override
virtual String toString() const override
{
std::string msg = std::format("[RuntimeError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name());
return FString(msg);
std::string msg = std::format("[RuntimeError] {} in [{}] {}",
this->message.toBasicString(),
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
}
virtual FString getErrorType() const override
{
return FString(u8"RuntimeError");
}
virtual String getErrorType() const override { return String(U"\1"); }
};
} // namespace Fig

View File

@@ -6,7 +6,6 @@
#include <print>
#include <vector>
namespace Fig
{
namespace ErrorLog
@@ -87,7 +86,7 @@ namespace Fig
constexpr const char *OnGray = "\033[48;2;128;128;128m";
}; // namespace TerminalColors
inline void coloredPrint(const char *colorCode, FString msg)
inline void coloredPrint(const char *colorCode, String msg)
{
std::print("{}{}{}", colorCode, msg.toBasicString(), TerminalColors::Reset);
}
@@ -97,34 +96,44 @@ namespace Fig
std::print("{}{}{}", colorCode, msg, TerminalColors::Reset);
}
inline void logFigErrorInterface(const FString &errorClass, const FString &errorMessage)
inline void logFigErrorInterface(const String &errorClass, const String &errorMessage)
{
namespace TC = TerminalColors;
coloredPrint(TC::LightWhite, "Uncaught Fig exception:\n");
coloredPrint(TC::LightRed, "");
coloredPrint(TC::LightWhite, U"Uncaught Fig exception:\n");
coloredPrint(TC::LightRed, U"");
coloredPrint(TC::Red, errorClass.toBasicString() + ": ");
coloredPrint(TC::Red, errorMessage.toBasicString() + "\n");
}
inline void logAddressableError(const AddressableError &err)
{
const FString &fileName = err.getSourcePath();
const std::vector<FString> &sourceLines = err.getSourceLines();
const String &fileName = err.getSourcePath();
const std::vector<String> &sourceLines = err.getSourceLines();
std::print("\n");
namespace TC = TerminalColors;
coloredPrint(TC::LightWhite, "An error occurred! ");
coloredPrint(TC::White, std::format("Fig {} ({})[{} {} bit on `{}`]\n",Core::VERSION, Core::COMPILE_TIME, Core::COMPILER, Core::ARCH, Core::PLATFORM));
coloredPrint(TC::LightRed, "");
coloredPrint(TC::LightRed, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString()));
coloredPrint(TC::White, std::format(" at {}:{} in file '{}'\n", err.getLine(), err.getColumn(), fileName.toBasicString()));
coloredPrint(TC::LightWhite, U"An error occurred! ");
coloredPrint(TC::White,
std::format("Fig {} ({})[{} {} bit on `{}`]\n",
Core::VERSION,
Core::COMPILE_TIME,
Core::COMPILER,
Core::ARCH,
Core::PLATFORM));
coloredPrint(TC::LightRed, U"");
coloredPrint(
TC::LightRed,
std::format("{}: {}\n", err.getErrorType().toBasicString(), String(err.getMessage()).toBasicString()));
coloredPrint(
TC::White,
std::format(" at {}:{} in file '{}'\n", err.getLine(), err.getColumn(), fileName.toBasicString()));
FString lineContent;
FString pointerLine;
String lineContent;
String pointerLine;
if (fileName != u8"<stdin>")
if (fileName != U"\1")
{
lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : u8"<No Source>");
lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : U"\1");
for (size_t i = 1; i < err.getColumn(); ++i)
{
if (lineContent[i - 1] == U'\t') { pointerLine += U'\t'; }
@@ -143,18 +152,34 @@ namespace Fig
coloredPrint(TC::LightBlue, std::format(" {}\n", lineContent.toBasicString()));
coloredPrint(TC::LightGreen, std::format(" {}\n", pointerLine.toBasicString()));
coloredPrint(TC::DarkGray, std::format("🔧 in function '{}' ({}:{})\n", err.src_loc.function_name(), err.src_loc.file_name(), err.src_loc.line()));
coloredPrint(TC::DarkGray,
std::format("🔧 in function '{}' ({}:{})\n",
err.src_loc.function_name(),
err.src_loc.file_name(),
err.src_loc.line()));
}
inline void logUnaddressableError(const UnaddressableError &err)
{
std::print("\n");
namespace TC = TerminalColors;
coloredPrint(TC::LightWhite, "An error occurred! ");
coloredPrint(TC::White, std::format("Fig {} ({})[{} {} bit on `{}`]\n", Core::VERSION, Core::COMPILE_TIME, Core::COMPILER, Core::ARCH, Core::PLATFORM));
coloredPrint(TC::DarkRed, "");
coloredPrint(TC::Red, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString()));
coloredPrint(TC::DarkGray, std::format("🔧 in function '{}' ({}:{})", err.src_loc.function_name(), err.src_loc.file_name(), err.src_loc.line()));
coloredPrint(TC::LightWhite, U"An error occurred! ");
coloredPrint(TC::White,
std::format("Fig {} ({})[{} {} bit on `{}`]\n",
Core::VERSION,
Core::COMPILE_TIME,
Core::COMPILER,
Core::ARCH,
Core::PLATFORM));
coloredPrint(TC::DarkRed, U"");
coloredPrint(
TC::Red,
std::format("{}: {}\n", err.getErrorType().toBasicString(), String(err.getMessage()).toBasicString()));
coloredPrint(TC::DarkGray,
std::format("🔧 in function '{}' ({}:{})",
err.src_loc.function_name(),
err.src_loc.file_name(),
err.src_loc.line()));
}
}; // namespace ErrorLog
}; // namespace Fig

View File

@@ -13,7 +13,7 @@
#include <Evaluator/Value/interface.hpp>
#include <Evaluator/Value/Type.hpp>
#include <Evaluator/Context/context_forward.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/value.hpp>
#include <Evaluator/Value/VariableSlot.hpp>
#include <Evaluator/Core/ExprResult.hpp>
@@ -26,7 +26,7 @@ namespace Fig
TypeInfo interfaceType;
TypeInfo structType;
std::unordered_map<FString, Function> implMethods;
std::unordered_map<String, Function> implMethods;
};
struct OperationRecord
@@ -49,11 +49,11 @@ namespace Fig
class Context : public std::enable_shared_from_this<Context>
{
private:
FString scopeName;
std::unordered_map<FString, std::shared_ptr<VariableSlot>> variables;
String scopeName;
std::unordered_map<String, std::shared_ptr<VariableSlot>> variables;
// std::unordered_map<std::size_t, Function> functions;
// std::unordered_map<std::size_t, FString> functionNames;
// std::unordered_map<std::size_t, String> functionNames;
// implRegistry <Struct, ordered list of ImplRecord>
std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash> implRegistry;
@@ -63,13 +63,13 @@ namespace Fig
ContextPtr parent;
Context(const Context &) = default;
Context(const FString &name, ContextPtr p = nullptr) : scopeName(name), parent(p) {}
Context(const String &name, ContextPtr p = nullptr) : scopeName(name), parent(p) {}
void setParent(ContextPtr _parent) { parent = _parent; }
void setScopeName(FString _name) { scopeName = std::move(_name); }
void setScopeName(String _name) { scopeName = std::move(_name); }
FString getScopeName() const { return scopeName; }
String getScopeName() const { return scopeName; }
void merge(const Context &c)
{
@@ -94,58 +94,58 @@ namespace Fig
return result;
}
std::shared_ptr<VariableSlot> get(const FString &name)
std::shared_ptr<VariableSlot> get(const String &name)
{
auto it = variables.find(name);
if (it != variables.end()) return it->second;
if (parent) return parent->get(name);
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
}
AccessModifier getAccessModifier(const FString &name)
AccessModifier getAccessModifier(const String &name)
{
if (variables.contains(name)) { return variables[name]->am; }
else if (parent != nullptr) { return parent->getAccessModifier(name); }
else
{
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
}
}
bool isVariableMutable(const FString &name)
bool isVariableMutable(const String &name)
{
AccessModifier am = getAccessModifier(name); // may throw
return !isAccessConst(am);
}
bool isVariablePublic(const FString &name)
bool isVariablePublic(const String &name)
{
AccessModifier am = getAccessModifier(name); // may throw
return isAccessPublic(am);
}
void set(const FString &name, ObjectPtr value)
void set(const String &name, ObjectPtr value)
{
if (variables.contains(name))
{
if (!isVariableMutable(name))
{
throw RuntimeError(FString(std::format("Variable '{}' is immutable", name.toBasicString())));
throw RuntimeError(String(std::format("Variable '{}' is immutable", name.toBasicString())));
}
variables[name]->value = value;
}
else if (parent != nullptr) { parent->set(name, value); }
else
{
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
}
}
void _update(const FString &name, ObjectPtr value)
void _update(const String &name, ObjectPtr value)
{
if (variables.contains(name)) { variables[name]->value = value; }
else if (parent != nullptr) { parent->_update(name, value); }
else
{
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
}
}
void def(const FString &name,
void def(const String &name,
const TypeInfo &ti,
AccessModifier am,
const ObjectPtr &value = Object::getNullInstance())
@@ -153,7 +153,7 @@ namespace Fig
if (containsInThisScope(name))
{
throw RuntimeError(
FString(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
String(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
}
variables[name] = std::make_shared<VariableSlot>(name, value, ti, am);
// if (ti == ValueType::StructType)
@@ -163,17 +163,17 @@ namespace Fig
// }
}
void
defReference(const FString &name, const TypeInfo &ti, AccessModifier am, std::shared_ptr<VariableSlot> target)
defReference(const String &name, const TypeInfo &ti, AccessModifier am, std::shared_ptr<VariableSlot> target)
{
if (containsInThisScope(name))
{
throw RuntimeError(
FString(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
String(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
}
variables[name] = std::make_shared<VariableSlot>(name, target->value, ti, am, true, target);
}
std::optional<FString> getFunctionName(std::size_t id)
std::optional<String> getFunctionName(std::size_t id)
{
for (auto &[name, slot] : variables)
{
@@ -185,7 +185,7 @@ namespace Fig
}
return std::nullopt;
}
// std::optional<FString> getStructName(std::size_t id)
// std::optional<String> getStructName(std::size_t id)
// {
// auto it = structTypeNames.find(id);
// if (it != structTypeNames.end())
@@ -201,21 +201,21 @@ namespace Fig
// return std::nullopt;
// }
// }
bool contains(const FString &name)
bool contains(const String &name)
{
if (variables.contains(name)) { return true; }
else if (parent != nullptr) { return parent->contains(name); }
return false;
}
bool containsInThisScope(const FString &name) const { return variables.contains(name); }
bool containsInThisScope(const String &name) const { return variables.contains(name); }
TypeInfo getTypeInfo(const FString &name) { return get(name)->declaredType; }
TypeInfo getTypeInfo(const String &name) { return get(name)->declaredType; }
bool isInFunctionContext()
{
ContextPtr ctx = shared_from_this();
while (ctx)
{
if (ctx->getScopeName().find(u8"<Function ") == 0) { return true; }
if (ctx->getScopeName().find(U"\1") == 0) { return true; }
ctx = ctx->parent;
}
return false;
@@ -225,10 +225,7 @@ namespace Fig
ContextPtr ctx = shared_from_this();
while (ctx)
{
if (ctx->getScopeName().find(u8"<While ") == 0 or ctx->getScopeName().find(u8"<For ") == 0)
{
return true;
}
if (ctx->getScopeName().find(U"\1") == 0 or ctx->getScopeName().find(U"\1") == 0) { return true; }
ctx = ctx->parent;
}
return false;
@@ -282,7 +279,7 @@ namespace Fig
list.push_back(record); // order is the level
}
bool hasMethodImplemented(const TypeInfo &structType, const FString &functionName) const
bool hasMethodImplemented(const TypeInfo &structType, const String &functionName) const
{
auto it = implRegistry.find(structType);
if (it != implRegistry.end())
@@ -296,7 +293,7 @@ namespace Fig
return parent && parent->hasMethodImplemented(structType, functionName);
}
bool hasDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) const
bool hasDefaultImplementedMethod(const TypeInfo &structType, const String &functionName) const
{
auto it = implRegistry.find(structType);
if (it == implRegistry.end()) return false;
@@ -325,7 +322,7 @@ namespace Fig
return false;
}
Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName)
Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const String &functionName)
{
// O(N²)
// SLOW
@@ -366,7 +363,7 @@ namespace Fig
assert(false);
}
const Function &getImplementedMethod(const TypeInfo &structType, const FString &functionName) const
const Function &getImplementedMethod(const TypeInfo &structType, const String &functionName) const
{
auto it = implRegistry.find(structType);
if (it != implRegistry.end())

View File

@@ -45,13 +45,11 @@ namespace Fig
case AstType::FunctionLiteralExpr: {
auto fnLiteral = std::static_pointer_cast<Ast::FunctionLiteralExprAst>(exp);
Ast::BlockStatement body = nullptr;
if (fnLiteral->isExprMode())
{
Ast::Expression exprBody = fnLiteral->getExprBody();
const Ast::AstAddressInfo &aai = exprBody->getAAI();
Ast::Return st = std::make_shared<Ast::ReturnSt>(exprBody);
st->setAAI(aai);
@@ -63,9 +61,8 @@ namespace Fig
else
{
body = fnLiteral->getBlockBody();
}
Function fn(FString(std::format("<LambdaFn>")),fnLiteral->paras, ValueType::Any, body, ctx
Function fn(String(std::format("<LambdaFn>")), fnLiteral->paras, ValueType::Any, body, ctx
/*
pass the ctx(fnLiteral eval context) as closure context
*/
@@ -81,7 +78,6 @@ namespace Fig
case AstType::ListExpr: {
auto lstExpr = std::static_pointer_cast<Ast::ListExprAst>(exp);
List list;
for (auto &exp : lstExpr->val) { list.push_back(check_unwrap(eval(exp, ctx))); }
return std::make_shared<Object>(std::move(list));
@@ -90,18 +86,18 @@ namespace Fig
case AstType::MapExpr: {
auto mapExpr = std::static_pointer_cast<Ast::MapExprAst>(exp);
Map map;
for (auto &[key, value] : mapExpr->val) {
for (auto &[key, value] : mapExpr->val)
{
map[check_unwrap(eval(key, ctx))] = check_unwrap(eval(value, ctx));
}
return std::make_shared<Object>(std::move(map));
}
default: {
throw RuntimeError(FString(std::format("err type of expr: {}", magic_enum::enum_name(type))));
throw RuntimeError(String(std::format("err type of expr: {}", magic_enum::enum_name(type))));
}
}
return Object::getNullInstance(); // ignore warning
}
};
}; // namespace Fig

View File

@@ -86,7 +86,7 @@ namespace Fig
{
ValueType::IntClass lv = lhs->as<ValueType::IntClass>();
ValueType::IntClass rv = rhs->as<ValueType::IntClass>();
if (rv == 0) { throw ValueError(FString(std::format("Modulo by zero: {} % {}", lv, rv))); }
if (rv == 0) { throw ValueError(String(std::format("Modulo by zero: {} % {}", lv, rv))); }
ValueType::IntClass result = lv / rv;
ValueType::IntClass r = lv % rv;
if (r != 0 && ((lv < 0) != (rv < 0))) { result -= 1; }
@@ -139,7 +139,7 @@ namespace Fig
return Object::getFalseInstance();
}
throw EvaluatorError(u8"TypeError",
throw EvaluatorError(U"TypeError",
std::format("Unsupported operator `is` for '{}' && '{}'",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString()),
@@ -155,7 +155,7 @@ namespace Fig
if (!rhs->is<StructType>())
{
throw EvaluatorError(
u8"OperatorError",
U"OperatorError",
std::format("Operator `as` requires right hand side operand a struct type, but got '{}'",
prettyType(rhs).toBasicString()),
bin->rexp);
@@ -183,7 +183,7 @@ namespace Fig
}
else if (sourceType == ValueType::String)
{
const FString &str = lhs->as<ValueType::StringClass>();
const String &str = lhs->as<ValueType::StringClass>();
if (targetType == ValueType::Int)
{
try
@@ -194,10 +194,10 @@ namespace Fig
catch (std::exception &e)
{
return ExprResult::error(
genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad int string {}",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString(),
str.toBasicString())),
genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad int string {}",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString(),
str.toBasicString())),
bin->rexp,
ctx));
}
@@ -211,22 +211,22 @@ namespace Fig
catch (std::exception &e)
{
return ExprResult::error(genTypeError(
FString(std::format("Cannot cast type `{}` to `{}`, bad double string {}",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString(),
str.toBasicString())),
String(std::format("Cannot cast type `{}` to `{}`, bad double string {}",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString(),
str.toBasicString())),
bin->rexp,
ctx));
}
}
if (targetType == ValueType::Bool)
{
if (str == u8"true") { return Object::getTrueInstance(); }
else if (str == u8"false") { return Object::getFalseInstance(); }
if (str == U"true") { return Object::getTrueInstance(); }
else if (str == U"false") { return Object::getFalseInstance(); }
return ExprResult::error(
genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad bool string {}",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString(),
genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad bool string {}",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString(),
str.toBasicString())),
bin->rexp,
ctx));
@@ -236,17 +236,19 @@ namespace Fig
{
if (targetType == ValueType::Int)
{
return IntPool::getInstance().createInt(static_cast<ValueType::IntClass>(lhs->as<ValueType::BoolClass>()));
return IntPool::getInstance().createInt(
static_cast<ValueType::IntClass>(lhs->as<ValueType::BoolClass>()));
}
if (targetType == ValueType::Double)
{
return std::make_shared<Object>(static_cast<ValueType::DoubleClass>(lhs->as<ValueType::BoolClass>()));
return std::make_shared<Object>(
static_cast<ValueType::DoubleClass>(lhs->as<ValueType::BoolClass>()));
}
}
return ExprResult::error(genTypeError(FString(std::format("Cannot cast type `{}` to `{}`",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString())),
return ExprResult::error(genTypeError(String(std::format("Cannot cast type `{}` to `{}`",
prettyType(lhs).toBasicString(),
prettyType(rhs).toBasicString())),
bin->rexp,
ctx));
});
@@ -429,7 +431,7 @@ namespace Fig
}
default:
throw EvaluatorError(u8"UnsupportedOp",
throw EvaluatorError(U"UnsupportedOp",
std::format("Unsupport operator '{}' for binary", magic_enum::enum_name(op)),
bin);
}

View File

@@ -9,11 +9,11 @@
namespace Fig
{
ExprResult Evaluator::executeFunction(const Function &fn,
const Ast::FunctionCallArgs &args,
ContextPtr fnCtx) // new context for fn, already filled paras
ExprResult Evaluator::executeFunction(const Function &fn,
const Ast::FunctionCallArgs &args,
ContextPtr fnCtx) // new context for fn, already filled paras
{
// const FString &fnName = fn.name;
// const String &fnName = fn.name;
if (fn.type == Function::Builtin || fn.type == Function::MemberType)
{
if (fn.type == Function::Builtin) { return fn.builtin(args.argv); }
@@ -27,14 +27,8 @@ namespace Fig
for (const auto &stmt : fn.body->stmts)
{
StatementResult sr = evalStatement(stmt, fnCtx);
if (sr.isError())
{
handle_error(sr, stmt, fnCtx);
}
if (!sr.isNormal())
{
return sr.result;
}
if (sr.isError()) { handle_error(sr, stmt, fnCtx); }
if (!sr.isNormal()) { return sr.result; }
}
return Object::getNullInstance();
}
@@ -43,14 +37,14 @@ namespace Fig
RvObject fnObj = check_unwrap(eval(call->callee, ctx));
if (fnObj->getTypeInfo() != ValueType::Function)
{
throw EvaluatorError(u8"ObjectNotCallable",
throw EvaluatorError(U"ObjectNotCallable",
std::format("Object `{}` isn't callable", fnObj->toString().toBasicString()),
call->callee);
}
const Function &fn = fnObj->as<Function>();
const FString &fnName = fn.name;
const String &fnName = fn.name;
const Ast::FunctionArguments &fnArgs = call->arg;
Ast::FunctionCallArgs evaluatedArgs;
@@ -59,7 +53,7 @@ namespace Fig
for (const auto &argExpr : fnArgs.argv) { evaluatedArgs.argv.push_back(check_unwrap(eval(argExpr, ctx))); }
if (fn.builtinParamCount != -1 && fn.builtinParamCount != evaluatedArgs.getLength())
{
throw EvaluatorError(u8"BuiltinArgumentMismatchError",
throw EvaluatorError(U"BuiltinArgumentMismatchError",
std::format("Builtin function '{}' expects {} arguments, but {} were provided",
fnName.toBasicString(),
fn.builtinParamCount,
@@ -73,7 +67,7 @@ namespace Fig
Ast::FunctionParameters fnParas = fn.paras;
// create new context for function call
auto newContext = std::make_shared<Context>(FString(std::format("<Function {}()>", fnName.toBasicString())),
auto newContext = std::make_shared<Context>(String(std::format("<Function {}()>", fnName.toBasicString())),
fn.closureContext);
if (fnParas.variadic)
@@ -84,24 +78,25 @@ namespace Fig
NormalFilling: {
if (fnArgs.getLength() < fnParas.posParas.size() || fnArgs.getLength() > fnParas.size())
{
throw RuntimeError(FString(std::format("Function '{}' expects {} to {} arguments, but {} were provided",
fnName.toBasicString(),
fnParas.posParas.size(),
fnParas.size(),
fnArgs.getLength())));
throw RuntimeError(String(std::format("Function '{}' expects {} to {} arguments, but {} were provided",
fnName.toBasicString(),
fnParas.posParas.size(),
fnParas.size(),
fnArgs.getLength())));
}
// positional parameters type check
size_t i;
for (i = 0; i < fnParas.posParas.size(); i++)
{
const TypeInfo &expectedType = actualType(check_unwrap(eval(fnParas.posParas[i].second, fn.closureContext))); // look up type info, if exists a type
// with the name, use it, else throw
const TypeInfo &expectedType = actualType(check_unwrap(
eval(fnParas.posParas[i].second, fn.closureContext))); // look up type info, if exists a type
// with the name, use it, else throw
ObjectPtr argVal = check_unwrap(eval(fnArgs.argv[i], ctx));
TypeInfo actualType = argVal->getTypeInfo();
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
{
throw EvaluatorError(u8"ArgumentTypeMismatchError",
throw EvaluatorError(U"ArgumentTypeMismatchError",
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
fnName.toBasicString(),
fnParas.posParas[i].first.toBasicString(),
@@ -122,7 +117,7 @@ namespace Fig
if (!isTypeMatch(expectedType, defaultVal, fn.closureContext))
{
throw EvaluatorError(
u8"DefaultParameterTypeError",
U"DefaultParameterTypeError",
std::format(
"In function '{}', default parameter '{}' has type '{}', which does not match the expected type '{}'",
fnName.toBasicString(),
@@ -136,7 +131,7 @@ namespace Fig
TypeInfo actualType = argVal->getTypeInfo();
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
{
throw EvaluatorError(u8"ArgumentTypeMismatchError",
throw EvaluatorError(U"ArgumentTypeMismatchError",
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
fnName.toBasicString(),
fnParas.defParas[defParamIndex].first.toBasicString(),
@@ -157,7 +152,7 @@ namespace Fig
// define parameters in new context
for (size_t j = 0; j < fnParas.size(); j++)
{
FString paramName;
String paramName;
TypeInfo paramType;
if (j < fnParas.posParas.size())
{
@@ -193,7 +188,7 @@ namespace Fig
if (!isTypeMatch(fn.retType, retVal, ctx))
{
throw EvaluatorError(u8"ReturnTypeMismatchError",
throw EvaluatorError(U"ReturnTypeMismatchError",
std::format("Function '{}' expects return type '{}', but got type '{}'",
fnName.toBasicString(),
fn.retType.toString().toBasicString(),

View File

@@ -10,10 +10,10 @@ namespace Fig
{
LvObject structeLv = check_unwrap_lv(evalLv(initExpr->structe, ctx));
ObjectPtr structTypeVal = structeLv.get();
const FString &structName = structeLv.name();
const String &structName = structeLv.name();
if (!structTypeVal->is<StructType>())
{
throw EvaluatorError(u8"NotAStructTypeError",
throw EvaluatorError(U"NotAStructTypeError",
std::format("'{}' is not a structure type", structName.toBasicString()),
initExpr);
}
@@ -27,7 +27,7 @@ namespace Fig
if (argSize > 1)
{
throw EvaluatorError(u8"StructInitArgumentMismatchError",
throw EvaluatorError(U"StructInitArgumentMismatchError",
std::format("Builtin class `{}` expects 0 or 1 argument, but {} were provided",
type.toString().toBasicString(),
argSize),
@@ -40,7 +40,7 @@ namespace Fig
if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function)
{
throw EvaluatorError(
u8"BuiltinNotConstructibleError",
U"BuiltinNotConstructibleError",
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
initExpr);
}
@@ -50,7 +50,7 @@ namespace Fig
ObjectPtr val = check_unwrap(eval(args[0].second, ctx));
auto err = [&](const char *msg) {
throw EvaluatorError(u8"BuiltinInitTypeMismatchError",
throw EvaluatorError(U"BuiltinInitTypeMismatchError",
std::format("Builtin `{}` constructor {}", type.toString().toBasicString(), msg),
initExpr);
};
@@ -121,7 +121,7 @@ namespace Fig
}
throw EvaluatorError(
u8"BuiltinNotConstructibleError",
U"BuiltinNotConstructibleError",
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
initExpr);
}
@@ -140,7 +140,7 @@ namespace Fig
size_t got = initExpr->args.size();
if (got > maxArgs || got < minArgs)
{
throw EvaluatorError(u8"StructInitArgumentMismatchError",
throw EvaluatorError(U"StructInitArgumentMismatchError",
std::format("Structure '{}' expects {} to {} fields, but {} were provided",
structName.toBasicString(),
minArgs,
@@ -149,9 +149,9 @@ namespace Fig
initExpr);
}
std::vector<std::pair<FString, ObjectPtr>> evaluatedArgs;
std::vector<std::pair<String, ObjectPtr>> evaluatedArgs;
auto evalArguments = [&evaluatedArgs, initExpr, ctx, this](){
auto evalArguments = [&evaluatedArgs, initExpr, ctx, this]() {
for (const auto &[argName, argExpr] : initExpr->args)
{
evaluatedArgs.push_back({argName, check_unwrap(eval(argExpr, ctx))});
@@ -159,8 +159,8 @@ namespace Fig
return ExprResult::normal(Object::getNullInstance());
};
ContextPtr instanceCtx =
std::make_shared<Context>(FString(std::format("<StructInstance {}>", structName.toBasicString())), defContext);
ContextPtr instanceCtx = std::make_shared<Context>(
String(std::format("<StructInstance {}>", structName.toBasicString())), defContext);
/*
3 ways of calling constructor
.1 Person {"Fig", 1, "IDK"};
@@ -176,7 +176,7 @@ namespace Fig
for (size_t i = 0; i < maxArgs; ++i)
{
const Field &field = structT.fields[i];
const FString &fieldName = field.name;
const String &fieldName = field.name;
const TypeInfo &expectedType = field.type;
if (i >= evaluatedArgs.size())
{
@@ -191,7 +191,7 @@ namespace Fig
if (!isTypeMatch(expectedType, defaultVal, ctx))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(),
fieldName.toBasicString(),
@@ -208,7 +208,7 @@ namespace Fig
if (!isTypeMatch(expectedType, argVal, ctx))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(),
fieldName.toBasicString(),
@@ -227,10 +227,10 @@ namespace Fig
for (size_t i = 0; i < maxArgs; ++i)
{
const Field &field = structT.fields[i];
const FString &fieldName = (field.name.empty() ? evaluatedArgs[i].first : field.name);
const String &fieldName = (field.name.empty() ? evaluatedArgs[i].first : field.name);
if (instanceCtx->containsInThisScope(fieldName))
{
throw EvaluatorError(u8"StructFieldRedeclarationError",
throw EvaluatorError(U"StructFieldRedeclarationError",
std::format("Field '{}' already initialized in structure '{}'",
fieldName.toBasicString(),
structName.toBasicString()),
@@ -248,7 +248,7 @@ namespace Fig
if (!isTypeMatch(expectedType, defaultVal, ctx))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(),
fieldName.toBasicString(),
@@ -264,7 +264,7 @@ namespace Fig
if (!isTypeMatch(field.type, argVal, ctx))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(),
fieldName.toBasicString(),
@@ -291,7 +291,7 @@ namespace Fig
[&argName](const Field &f) { return f.name == argName; });
if (fieldIt == structT.fields.end())
{
// throw EvaluatorError(u8"StructFieldNotFoundError",
// throw EvaluatorError(U"StructFieldNotFoundError",
// std::format("Field '{}' not found in structure '{}'",
// argName.toBasicString(),
// structName.toBasicString()),
@@ -303,7 +303,7 @@ namespace Fig
if (!isTypeMatch(field.type, argVal, ctx))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(),
field.name.toBasicString(),
@@ -332,7 +332,7 @@ namespace Fig
if (!isTypeMatch(field.type, defaultVal, ctx))
{
throw EvaluatorError(
u8"StructFieldTypeMismatchError",
U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(),
field.name.toBasicString(),
@@ -350,7 +350,7 @@ namespace Fig
// load struct method
for (auto &[id, fn] : stDefCtx->getFunctions())
{
const FString &funcName = fn.name;
const String &funcName = fn.name;
const auto &funcSlot = stDefCtx->get(funcName);
instanceCtx->def(funcName,
@@ -361,4 +361,4 @@ namespace Fig
return std::make_shared<Object>(StructInstance(structT.type, instanceCtx));
}
};
}; // namespace Fig

View File

@@ -8,7 +8,7 @@ namespace Fig
{
ExprResult Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
{
const FString &name = var->name;
const String &name = var->name;
// 调试信息
// std::cerr << "=== DEBUG evalVarExpr ===" << std::endl;
@@ -38,14 +38,14 @@ namespace Fig
// }
// end
if (!ctx->contains(name)) { throw EvaluatorError(u8"UndeclaredIdentifierError", name, var); }
if (!ctx->contains(name)) { throw EvaluatorError(U"UndeclaredIdentifierError", name, var); }
return LvObject(ctx->get(name), ctx);
}
ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx)
{
// LvObject base = evalLv(me->base, ctx);
RvObject baseVal = check_unwrap(eval(me->base, ctx));
const FString &member = me->member;
const String &member = me->member;
if (baseVal->getTypeInfo() == ValueType::Module)
{
// std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl;
@@ -74,7 +74,7 @@ namespace Fig
}
else
{
throw EvaluatorError(u8"VariableNotFoundError",
throw EvaluatorError(U"VariableNotFoundError",
std::format("`{}` has not variable '{}', check if it is public",
baseVal->toString().toBasicString(),
member.toBasicString()),
@@ -118,7 +118,7 @@ namespace Fig
if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found
{
throw EvaluatorError(
u8"NoAttributeError",
U"NoAttributeError",
std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()),
me->base);
}
@@ -153,7 +153,7 @@ namespace Fig
}
else
{
throw EvaluatorError(u8"NoAttributeError",
throw EvaluatorError(U"NoAttributeError",
std::format("`{}` has not attribute '{}' and no interfaces have been implemented it",
baseVal->toString().toBasicString(),
member.toBasicString()),
@@ -172,7 +172,7 @@ namespace Fig
if (index->getTypeInfo() != ValueType::Int)
{
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
ie->index);
}
@@ -181,7 +181,7 @@ namespace Fig
if (indexVal >= list.size())
{
throw EvaluatorError(
u8"IndexOutOfRangeError",
U"IndexOutOfRangeError",
std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()),
ie->index);
}
@@ -193,16 +193,16 @@ namespace Fig
if (index->getTypeInfo() != ValueType::Int)
{
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
ie->index);
}
FString &string = base->as<ValueType::StringClass>();
String &string = base->as<ValueType::StringClass>();
ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
if (indexVal >= string.length())
{
throw EvaluatorError(
u8"IndexOutOfRangeError",
U"IndexOutOfRangeError",
std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()),
ie->index);
}
@@ -211,7 +211,7 @@ namespace Fig
else
{
throw EvaluatorError(
u8"NoSubscriptableError",
U"NoSubscriptableError",
std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()),
ie->base);
}
@@ -239,7 +239,7 @@ namespace Fig
}
default: {
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
exp);
}

View File

@@ -3,7 +3,7 @@
#include <Ast/Expressions/FunctionCall.hpp>
#include <Ast/astBase.hpp>
#include <Ast/functionParameters.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Core/StatementResult.hpp>
#include <Evaluator/Value/Type.hpp>
#include <Evaluator/Value/structType.hpp>
@@ -32,7 +32,7 @@ namespace Fig
if (ctx->containsInThisScope(varDef->name))
{
throw EvaluatorError(
u8"RedeclarationError",
U"RedeclarationError",
std::format("Variable `{}` already declared in this scope", varDef->name.toBasicString()),
varDef);
}
@@ -51,7 +51,7 @@ namespace Fig
if (value != nullptr && !isTypeMatch(declaredType, value, ctx))
{
throw EvaluatorError(u8"TypeError",
throw EvaluatorError(U"TypeError",
std::format("Variable `{}` expects init-value type `{}`, but got '{}'",
varDef->name.toBasicString(),
prettyType(declaredTypeValue).toBasicString(),
@@ -73,11 +73,11 @@ namespace Fig
case FunctionDefSt: {
auto fnDef = std::static_pointer_cast<Ast::FunctionDefSt>(stmt);
const FString &fnName = fnDef->name;
const String &fnName = fnDef->name;
if (ctx->containsInThisScope(fnName))
{
throw EvaluatorError(
u8"RedeclarationError",
U"RedeclarationError",
std::format("Function `{}` already declared in this scope", fnName.toBasicString()),
fnDef);
}
@@ -102,16 +102,16 @@ namespace Fig
if (ctx->containsInThisScope(stDef->name))
{
throw EvaluatorError(
u8"RedeclarationError",
U"RedeclarationError",
std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()),
stDef);
}
TypeInfo type(stDef->name, true); // register type name
ContextPtr defContext = std::make_shared<Context>(FString(std::format("<Struct {} at {}:{}>",
stDef->name.toBasicString(),
stDef->getAAI().line,
stDef->getAAI().column)),
ContextPtr defContext = std::make_shared<Context>(String(std::format("<Struct {} at {}:{}>",
stDef->name.toBasicString(),
stDef->getAAI().line,
stDef->getAAI().column)),
ctx);
ObjectPtr structTypeObj = std::make_shared<Object>(StructType(type, defContext, {}));
@@ -124,12 +124,12 @@ namespace Fig
structTypeObj); // predef to itself, always const
std::vector<Field> fields;
std::vector<FString> _fieldNames;
std::vector<String> _fieldNames;
for (Ast::StructDefField field : stDef->fields)
{
if (Utils::vectorContains(field.fieldName, _fieldNames))
{
throw EvaluatorError(u8"RedeclarationError",
throw EvaluatorError(U"RedeclarationError",
std::format("Field '{}' already defined in structure '{}'",
field.fieldName.toBasicString(),
stDef->name.toBasicString()),
@@ -151,7 +151,7 @@ namespace Fig
{
if (st->getType() != Ast::AstType::FunctionDefSt)
{
throw EvaluatorError(u8"UnexpectedStatementInStructError",
throw EvaluatorError(U"UnexpectedStatementInStructError",
std::format("Unexpected statement `{}` in struct declaration",
st->toString().toBasicString()),
st);
@@ -164,12 +164,12 @@ namespace Fig
case InterfaceDefSt: {
auto ifd = std::static_pointer_cast<Ast::InterfaceDefAst>(stmt);
const FString &interfaceName = ifd->name;
const String &interfaceName = ifd->name;
if (ctx->containsInThisScope(interfaceName))
{
throw EvaluatorError(
u8"RedeclarationError",
U"RedeclarationError",
std::format("Interface `{}` already declared in this scope", interfaceName.toBasicString()),
ifd);
}
@@ -188,7 +188,7 @@ namespace Fig
TypeInfo interfaceType(ip->interfaceName);
if (ctx->hasImplRegisted(structType, interfaceType))
{
throw EvaluatorError(u8"DuplicateImplError",
throw EvaluatorError(U"DuplicateImplError",
std::format("Duplicate implement `{}` for `{}`",
interfaceType.toString().toBasicString(),
structType.toString().toBasicString()),
@@ -196,13 +196,13 @@ namespace Fig
}
if (!ctx->contains(ip->interfaceName))
{
throw EvaluatorError(u8"InterfaceNotFoundError",
throw EvaluatorError(U"InterfaceNotFoundError",
std::format("Interface '{}' not found", ip->interfaceName.toBasicString()),
ip);
}
if (!ctx->contains(ip->structName))
{
throw EvaluatorError(u8"StructNotFoundError",
throw EvaluatorError(U"StructNotFoundError",
std::format("Struct '{}' not found", ip->structName.toBasicString()),
ip);
}
@@ -218,21 +218,21 @@ namespace Fig
if (!interfaceObj->is<InterfaceType>())
{
throw EvaluatorError(
u8"NotAInterfaceError",
U"NotAInterfaceError",
std::format("Variable `{}` is not a interface", ip->interfaceName.toBasicString()),
ip);
}
if (!structTypeObj->is<StructType>())
{
throw EvaluatorError(
u8"NotAStructType",
U"NotAStructType",
std::format("Variable `{}` is not a struct type", ip->structName.toBasicString()),
ip);
}
auto &implementMethods = ip->methods;
if (ip->interfaceName == u8"Operation")
if (ip->interfaceName == U"Operation")
{
// 运算符重载
/*
@@ -243,52 +243,52 @@ namespace Fig
*/
if (ValueType::isTypeBuiltin(structType))
{
throw EvaluatorError(u8"BadUserError",
throw EvaluatorError(U"BadUserError",
std::format("Don't overload built-in type operators plz! `{}`",
prettyType(structTypeObj).toBasicString()),
ip);
}
using enum Ast::Operator;
static const std::unordered_map<FString, std::pair<Ast::Operator, size_t>> magic_name_to_op = {
static const std::unordered_map<String, std::pair<Ast::Operator, size_t>> magic_name_to_op = {
// 算术
{u8"Add", {Ast::Operator::Add, 2}},
{u8"Sub", {Ast::Operator::Subtract, 2}},
{u8"Mul", {Ast::Operator::Multiply, 2}},
{u8"Div", {Ast::Operator::Divide, 2}},
{u8"Mod", {Ast::Operator::Modulo, 2}},
{u8"Pow", {Ast::Operator::Power, 2}},
{U"Add", {Ast::Operator::Add, 2}},
{U"Sub", {Ast::Operator::Subtract, 2}},
{U"Mul", {Ast::Operator::Multiply, 2}},
{U"Div", {Ast::Operator::Divide, 2}},
{U"Mod", {Ast::Operator::Modulo, 2}},
{U"Pow", {Ast::Operator::Power, 2}},
// 逻辑(一元)
{u8"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号
{u8"Not", {Ast::Operator::Not, 1}},
{U"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号
{U"Not", {Ast::Operator::Not, 1}},
// 逻辑(二元)
{u8"And", {Ast::Operator::And, 2}},
{u8"Or", {Ast::Operator::Or, 2}},
{U"And", {Ast::Operator::And, 2}},
{U"Or", {Ast::Operator::Or, 2}},
// 比较
{u8"Equal", {Ast::Operator::Equal, 2}},
{u8"NotEqual", {Ast::Operator::NotEqual, 2}},
{u8"LessThan", {Ast::Operator::Less, 2}},
{u8"LessEqual", {Ast::Operator::LessEqual, 2}},
{u8"GreaterThan", {Ast::Operator::Greater, 2}},
{u8"GreaterEqual", {Ast::Operator::GreaterEqual, 2}},
{u8"Is", {Ast::Operator::Is, 2}},
{U"Equal", {Ast::Operator::Equal, 2}},
{U"NotEqual", {Ast::Operator::NotEqual, 2}},
{U"LessThan", {Ast::Operator::Less, 2}},
{U"LessEqual", {Ast::Operator::LessEqual, 2}},
{U"GreaterThan", {Ast::Operator::Greater, 2}},
{U"GreaterEqual", {Ast::Operator::GreaterEqual, 2}},
{U"Is", {Ast::Operator::Is, 2}},
// 位运算(一元)
{u8"BitNot", {Ast::Operator::BitNot, 1}},
{U"BitNot", {Ast::Operator::BitNot, 1}},
// 位运算(二元)
{u8"BitAnd", {Ast::Operator::BitAnd, 2}},
{u8"BitOr", {Ast::Operator::BitOr, 2}},
{u8"BitXor", {Ast::Operator::BitXor, 2}},
{u8"ShiftLeft", {Ast::Operator::ShiftLeft, 2}},
{u8"ShiftRight", {Ast::Operator::ShiftRight, 2}},
{U"BitAnd", {Ast::Operator::BitAnd, 2}},
{U"BitOr", {Ast::Operator::BitOr, 2}},
{U"BitXor", {Ast::Operator::BitXor, 2}},
{U"ShiftLeft", {Ast::Operator::ShiftLeft, 2}},
{U"ShiftRight", {Ast::Operator::ShiftRight, 2}},
};
for (auto &implMethod : implementMethods)
{
const FString &opName = implMethod.name;
const String &opName = implMethod.name;
if (!magic_name_to_op.contains(opName))
{
// ... 现在忽略
@@ -303,7 +303,7 @@ namespace Fig
if (ctx->hasOperatorImplemented(structType, op, (expectArgCnt == 1 ? true : false)))
{
throw EvaluatorError(
u8"DuplicateImplementError",
U"DuplicateImplementError",
std::format("{} has already implement by another interface", opName.toBasicString()),
ip);
}
@@ -312,7 +312,7 @@ namespace Fig
if (paraCnt != expectArgCnt || implMethod.paras.size() != expectArgCnt)
{
// 特化报错,更详细易读
throw EvaluatorError(u8"InterfaceSignatureMismatch",
throw EvaluatorError(U"InterfaceSignatureMismatch",
std::format("Operator {} for {} arg count must be {}, got {}",
opName.toBasicString(),
structLv.name().toBasicString(),
@@ -321,10 +321,10 @@ namespace Fig
ip);
}
FString opFnName(u8"Operation." + prettyType(structTypeObj) + u8"." + opName);
String opFnName(U"Operation." + prettyType(structTypeObj) + U"." + opName);
ContextPtr fnCtx = std::make_shared<Context>(
FString(std::format("<Function {}>", opFnName.toBasicString())), ctx);
String(std::format("<Function {}>", opFnName.toBasicString())), ctx);
const auto &fillOpFnParas = [this, structType, implMethod, opFnName, fnCtx, ctx, paraCnt](
const std::vector<ObjectPtr> &args) {
@@ -336,7 +336,7 @@ namespace Fig
if (paraType != ValueType::Any && paraType != structType)
{
throw EvaluatorError(
u8"ParameterTypeError",
U"ParameterTypeError",
std::format("Invalid op fn parameter type '{}' of `{}`, must be `{}`",
paraType.toString().toBasicString(),
paras.posParas[i].first.toBasicString(),
@@ -385,12 +385,12 @@ namespace Fig
// ===== interface implementation validation =====
ImplRecord record{interfaceType, structType, {}};
std::unordered_map<FString, Ast::InterfaceMethod> ifaceMethods;
std::unordered_map<String, Ast::InterfaceMethod> ifaceMethods;
for (auto &m : interface.methods)
{
if (ifaceMethods.contains(m.name))
{
throw EvaluatorError(u8"InterfaceDuplicateMethodError",
throw EvaluatorError(U"InterfaceDuplicateMethodError",
std::format("Interface '{}' has duplicate method '{}'",
interfaceType.toString().toBasicString(),
m.name.toBasicString()),
@@ -399,16 +399,16 @@ namespace Fig
ifaceMethods[m.name] = m;
}
std::unordered_set<FString> implemented;
std::unordered_set<String> implemented;
for (auto &implMethod : implementMethods)
{
const FString &name = implMethod.name;
const String &name = implMethod.name;
// ---- redundant impl ----
if (!ifaceMethods.contains(name))
{
throw EvaluatorError(u8"RedundantImplementationError",
throw EvaluatorError(U"RedundantImplementationError",
std::format("Struct '{}' implements extra method '{}' "
"which is not required by interface '{}'",
structType.toString().toBasicString(),
@@ -419,7 +419,7 @@ namespace Fig
if (implemented.contains(name))
{
throw EvaluatorError(u8"DuplicateImplementMethodError",
throw EvaluatorError(U"DuplicateImplementMethodError",
std::format("Duplicate implement method '{}'", name.toBasicString()),
ip);
}
@@ -429,7 +429,7 @@ namespace Fig
// ---- signature check ----
if (!isInterfaceSignatureMatch(implMethod, ifMethod))
{
throw EvaluatorError(u8"InterfaceSignatureMismatch",
throw EvaluatorError(U"InterfaceSignatureMismatch",
std::format("Interface method '{}({})' signature mismatch with "
"implementation '{}({})'",
ifMethod.name.toBasicString(),
@@ -441,7 +441,7 @@ namespace Fig
if (ctx->hasMethodImplemented(structType, name))
{
throw EvaluatorError(u8"DuplicateImplementMethodError",
throw EvaluatorError(U"DuplicateImplementMethodError",
std::format("Method '{}' already implemented by another interface "
"for struct '{}'",
name.toBasicString(),
@@ -463,7 +463,7 @@ namespace Fig
if (m.hasDefaultBody()) continue;
throw EvaluatorError(u8"MissingImplementationError",
throw EvaluatorError(U"MissingImplementationError",
std::format("Struct '{}' does not implement required interface method '{}' "
"and interface '{}' provides no default implementation",
structType.toString().toBasicString(),
@@ -482,7 +482,7 @@ namespace Fig
if (condVal->getTypeInfo() != ValueType::Bool)
{
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
ifSt->condition);
}
@@ -494,7 +494,7 @@ namespace Fig
if (elifCondVal->getTypeInfo() != ValueType::Bool)
{
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
ifSt->condition);
}
@@ -511,13 +511,13 @@ namespace Fig
if (condVal->getTypeInfo() != ValueType::Bool)
{
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
whileSt->condition);
}
if (!condVal->as<ValueType::BoolClass>()) { break; }
ContextPtr loopContext = std::make_shared<Context>(
FString(std::format("<While {}:{}>", whileSt->getAAI().line, whileSt->getAAI().column)),
String(std::format("<While {}:{}>", whileSt->getAAI().line, whileSt->getAAI().column)),
ctx); // every loop has its own context
StatementResult sr = evalBlockStatement(whileSt->body, loopContext);
if (sr.shouldReturn()) { return sr; }
@@ -529,7 +529,7 @@ namespace Fig
case ForSt: {
auto forSt = std::static_pointer_cast<Ast::ForSt>(stmt);
ContextPtr loopContext = std::make_shared<Context>(
FString(std::format("<For {}:{}>", forSt->getAAI().line, forSt->getAAI().column)),
String(std::format("<For {}:{}>", forSt->getAAI().line, forSt->getAAI().column)),
ctx); // for loop has its own context
evalStatement(forSt->initSt,
@@ -543,14 +543,14 @@ namespace Fig
if (condVal->getTypeInfo() != ValueType::Bool)
{
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
forSt->condition);
}
if (!condVal->as<ValueType::BoolClass>()) { break; }
iteration++;
ContextPtr iterationContext = std::make_shared<Context>(
FString(std::format(
String(std::format(
"<For {}:{}, Iteration {}>", forSt->getAAI().line, forSt->getAAI().column, iteration)),
loopContext); // every loop has its own context
StatementResult sr = evalBlockStatement(forSt->body, iterationContext);
@@ -571,7 +571,7 @@ namespace Fig
auto tryst = std::static_pointer_cast<Ast::TrySt>(stmt);
ContextPtr tryCtx = std::make_shared<Context>(
FString(std::format("<Try at {}:{}>", tryst->getAAI().line, tryst->getAAI().column)), ctx);
String(std::format("<Try at {}:{}>", tryst->getAAI().line, tryst->getAAI().column)), ctx);
StatementResult sr = StatementResult::normal();
bool crashed = false;
for (auto &stmt : tryst->body->stmts)
@@ -586,13 +586,12 @@ namespace Fig
bool catched = false;
for (auto &cat : tryst->catches)
{
const FString &errVarName = cat.errVarName;
const String &errVarName = cat.errVarName;
TypeInfo errVarType = (cat.hasType ? TypeInfo(cat.errVarType) : ValueType::Any);
if (isTypeMatch(errVarType, sr.result, ctx))
{
ContextPtr catchCtx = std::make_shared<Context>(
FString(
std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
String(std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
ctx);
catchCtx->def(errVarName, errVarType, AccessModifier::Normal, sr.result);
sr = evalBlockStatement(cat.body, catchCtx);
@@ -602,7 +601,7 @@ namespace Fig
}
if (!catched && crashed)
{
throw EvaluatorError(u8"UncaughtExceptionError",
throw EvaluatorError(U"UncaughtExceptionError",
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
tryst);
}
@@ -616,7 +615,7 @@ namespace Fig
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);
throw EvaluatorError(U"TypeError", U"Why did you throw a null?", ts);
}
return StatementResult::errorFlow(value);
}
@@ -632,11 +631,11 @@ namespace Fig
case BreakSt: {
if (!ctx->parent)
{
throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt);
throw EvaluatorError(U"BreakOutsideLoopError", U"`break` statement outside loop", stmt);
}
if (!ctx->isInLoopContext())
{
throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt);
throw EvaluatorError(U"BreakOutsideLoopError", U"`break` statement outside loop", stmt);
}
return StatementResult::breakFlow();
}
@@ -644,11 +643,11 @@ namespace Fig
case ContinueSt: {
if (!ctx->parent)
{
throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt);
throw EvaluatorError(U"ContinueOutsideLoopError", U"`continue` statement outside loop", stmt);
}
if (!ctx->isInLoopContext())
{
throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt);
throw EvaluatorError(U"ContinueOutsideLoopError", U"`continue` statement outside loop", stmt);
}
return StatementResult::continueFlow();
}
@@ -662,13 +661,13 @@ namespace Fig
auto block = std::static_pointer_cast<Ast::BlockStatementAst>(stmt);
ContextPtr blockCtx = std::make_shared<Context>(
FString(std::format("<Block at {}:{}>", block->getAAI().line, block->getAAI().column)), ctx);
String(std::format("<Block at {}:{}>", block->getAAI().line, block->getAAI().column)), ctx);
return evalBlockStatement(block, blockCtx);
}
default:
throw RuntimeError(
FString(std::format("Feature stmt {} unsupported yet", magic_enum::enum_name(stmt->getType()))));
String(std::format("Feature stmt {} unsupported yet", magic_enum::enum_name(stmt->getType()))));
}
}
}; // namespace Fig

View File

@@ -11,7 +11,7 @@ namespace Fig
if (condVal->getTypeInfo() != ValueType::Bool)
{
throw EvaluatorError(
u8"TypeError",
U"TypeError",
std::format("Condition must be boolean, got '{}'", prettyType(condVal).toBasicString()),
te->condition);
}

View File

@@ -39,7 +39,7 @@ namespace Fig
return tryInvokeOverloadFn(value, [value]() { return std::make_shared<Object>(bit_not(*value)); });
}
default: {
throw EvaluatorError(u8"UnsupportedOpError",
throw EvaluatorError(U"UnsupportedOpError",
std::format("Unsupported op '{}' for unary expression", magic_enum::enum_name(op)),
un);
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/value_forward.hpp>
#include <Evaluator/Value/LvObject.hpp>

View File

@@ -6,7 +6,7 @@
namespace Fig
{
std::filesystem::path Evaluator::resolveModulePath(const std::vector<FString> &pathVec)
std::filesystem::path Evaluator::resolveModulePath(const std::vector<String> &pathVec)
{
namespace fs = std::filesystem;
@@ -32,13 +32,13 @@ namespace Fig
import comp.config;
*/
const FString &modPathStrTop = pathVec.at(0);
const String &modPathStrTop = pathVec.at(0);
fs::path modPath;
bool found = false;
for (auto &parentFolder : pathToFind)
{
modPath = parentFolder / FString(modPathStrTop + u8".fig").toBasicString();
modPath = parentFolder / String(modPathStrTop + U".fig").toBasicString();
if (fs::exists(modPath))
{
path = modPath;
@@ -50,16 +50,16 @@ namespace Fig
modPath = parentFolder / modPathStrTop.toBasicString();
if (fs::is_directory(modPath)) // comp is a directory
{
modPath = modPath / FString(modPathStrTop + u8".fig").toBasicString();
modPath = modPath / String(modPathStrTop + U".fig").toBasicString();
/*
if module name is a directory, we require [module
name].fig at the directory
*/
if (!fs::exists(modPath))
{
throw RuntimeError(FString(std::format("requires module file, {}\\{}",
modPathStrTop.toBasicString(),
FString(modPathStrTop + u8".fig").toBasicString())));
throw RuntimeError(String(std::format("requires module file, {}\\{}",
modPathStrTop.toBasicString(),
String(modPathStrTop + U".fig").toBasicString())));
}
found = true;
path = modPath;
@@ -69,19 +69,19 @@ namespace Fig
}
if (!found)
throw RuntimeError(FString(std::format("Could not find module `{}`", modPathStrTop.toBasicString())));
throw RuntimeError(String(std::format("Could not find module `{}`", modPathStrTop.toBasicString())));
bool found2 = false;
for (size_t i = 1; i < pathVec.size(); ++i) // has next module
{
const FString &next = pathVec.at(i);
const String &next = pathVec.at(i);
modPath = modPath.parent_path(); // get the folder
modPath = modPath / FString(next + u8".fig").toBasicString();
modPath = modPath / String(next + U".fig").toBasicString();
if (fs::exists(modPath))
{
if (i != pathVec.size() - 1)
throw RuntimeError(FString(std::format(
throw RuntimeError(String(std::format(
"expects {} as parent directory and find next module, but got a file", next.toBasicString())));
// it's the last module
found2 = true;
@@ -91,14 +91,14 @@ namespace Fig
// `next` is a folder
modPath = modPath.parent_path() / next.toBasicString();
if (!fs::exists(modPath))
throw RuntimeError(FString(std::format("Could not find module `{}`", next.toBasicString())));
throw RuntimeError(String(std::format("Could not find module `{}`", next.toBasicString())));
if (i == pathVec.size() - 1)
{
// `next` is the last module
modPath = modPath / FString(next + u8".fig").toBasicString();
modPath = modPath / String(next + U".fig").toBasicString();
if (!fs::exists(modPath))
{
throw RuntimeError(FString(std::format(
throw RuntimeError(String(std::format(
"expects {} as parent directory and find next module, but got a file", next.toBasicString())));
}
found2 = true;
@@ -107,8 +107,8 @@ namespace Fig
}
if (!found2 && !fs::exists(modPath))
throw RuntimeError(FString(std::format("Could not find module `{}`", pathVec.end()->toBasicString())));
throw RuntimeError(String(std::format("Could not find module `{}`", pathVec.end()->toBasicString())));
return path;
}
};
}; // namespace Fig

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/value.hpp>
namespace Fig

View File

@@ -1,7 +1,7 @@
#pragma once
#include <Evaluator/Value/value.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/value_forward.hpp>
#include <Evaluator/Value/Type.hpp>
#include <array>

View File

@@ -24,18 +24,15 @@ namespace Fig
ContextPtr ctx;
LvObject(std::shared_ptr<VariableSlot> _slot, ContextPtr _ctx) :
slot(std::move(_slot)), ctx(_ctx)
LvObject(std::shared_ptr<VariableSlot> _slot, ContextPtr _ctx) : slot(std::move(_slot)), ctx(_ctx)
{
kind = Kind::Variable;
}
LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) :
value(_v), numIndex(_index), ctx(_ctx)
LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) : value(_v), numIndex(_index), ctx(_ctx)
{
kind = _kind;
}
LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) :
value(_v), mapIndex(_index), ctx(_ctx)
LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) : value(_v), mapIndex(_index), ctx(_ctx)
{
kind = _kind;
}
@@ -51,27 +48,26 @@ namespace Fig
{
List &list = value->as<List>();
if (numIndex >= list.size())
throw RuntimeError(FString(
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
throw RuntimeError(
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
return list.at(numIndex).value;
}
else if (kind == Kind::MapElement) // map
{
Map &map = value->as<Map>();
if (!map.contains(mapIndex))
throw RuntimeError(FString(
std::format("Key {} not found", mapIndex->toString().toBasicString())));
throw RuntimeError(String(std::format("Key {} not found", mapIndex->toString().toBasicString())));
return map.at(mapIndex);
}
else
{
// string
FString &string = value->as<ValueType::StringClass>();
String &string = value->as<ValueType::StringClass>();
if (numIndex >= string.length())
throw RuntimeError(FString(
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
throw RuntimeError(
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
return std::make_shared<Object>(string.getRealChar(numIndex));
return std::make_shared<Object>(String(string[numIndex]));
}
}
@@ -82,26 +78,21 @@ namespace Fig
auto s = resolve(slot);
if (!isTypeMatch(s->declaredType, v, ctx))
{
throw RuntimeError(
FString(
std::format("Variable `{}` expects type `{}`, but got '{}'",
s->name.toBasicString(),
s->declaredType.toString().toBasicString(),
prettyType(v).toBasicString())));
throw RuntimeError(String(std::format("Variable `{}` expects type `{}`, but got '{}'",
s->name.toBasicString(),
s->declaredType.toString().toBasicString(),
prettyType(v).toBasicString())));
}
if (isAccessConst(s->am))
{
throw RuntimeError(FString(
std::format("Variable `{}` is immutable", s->name.toBasicString())));
throw RuntimeError(String(std::format("Variable `{}` is immutable", s->name.toBasicString())));
}
s->value = v;
}
else if (kind == Kind::ListElement)
{
List &list = value->as<List>();
if (numIndex >= list.size())
throw RuntimeError(FString(
std::format("Index {} out of range", numIndex)));
if (numIndex >= list.size()) throw RuntimeError(String(std::format("Index {} out of range", numIndex)));
list[numIndex] = v;
}
else if (kind == Kind::MapElement) // map
@@ -111,25 +102,23 @@ namespace Fig
}
else if (kind == Kind::StringElement)
{
FString &string = value->as<ValueType::StringClass>();
String &string = value->as<ValueType::StringClass>();
if (numIndex >= string.length())
throw RuntimeError(FString(
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
throw RuntimeError(
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
if (v->getTypeInfo() != ValueType::String)
throw RuntimeError(FString(
std::format("Could not assign {} to sub string", v->toString().toBasicString())
));
const FString &strReplace = v->as<ValueType::StringClass>();
throw RuntimeError(
String(std::format("Could not assign {} to sub string", v->toString().toBasicString())));
const String &strReplace = v->as<ValueType::StringClass>();
if (strReplace.length() > 1)
throw RuntimeError(FString(
std::format("Could not assign {} to sub string, expects length 1", v->toString().toBasicString())
));
string.realReplace(numIndex, strReplace);
throw RuntimeError(String(std::format("Could not assign {} to sub string, expects length 1",
v->toString().toBasicString())));
string.replace(numIndex, strReplace.length(), strReplace);
}
}
FString name() const { return resolve(slot)->name; }
String name() const { return resolve(slot)->name; }
TypeInfo declaredType() const { return resolve(slot)->declaredType; }
AccessModifier access() const { return resolve(slot)->am; }

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <unordered_set>
#include <variant>
@@ -14,23 +14,23 @@ namespace Fig
private:
size_t id;
std::map<FString, size_t> &getTypeMap()
std::map<String, size_t> &getTypeMap()
{
static std::map<FString, size_t> typeMap;
static std::map<String, size_t> typeMap;
return typeMap;
}
public:
friend class TypeInfoHash;
FString name;
String name;
FString toString() const { return name; }
String toString() const { return name; }
size_t getInstanceID() const { return id; }
TypeInfo();
explicit TypeInfo(const FString &_name, bool reg = false);
explicit TypeInfo(const String &_name, bool reg = false);
TypeInfo(const TypeInfo &other) = default;
bool operator==(const TypeInfo &other) const { return id == other.id; }
@@ -63,7 +63,7 @@ namespace Fig
using DoubleClass = double;
using BoolClass = bool;
using NullClass = std::monostate;
using StringClass = FString;
using StringClass = Fig::String;
inline bool isTypeBuiltin(const TypeInfo &type)
{

View File

@@ -1,8 +1,7 @@
#pragma once
#include <Ast/AccessModifier.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/Type.hpp>
#include <Evaluator/Value/value_forward.hpp>
@@ -12,7 +11,7 @@ namespace Fig
struct VariableSlot
{
FString name;
String name;
ObjectPtr value;
TypeInfo declaredType;
AccessModifier am;
@@ -20,4 +19,4 @@ namespace Fig
bool isRef = false;
std::shared_ptr<VariableSlot> refTarget;
};
}
} // namespace Fig

View File

@@ -16,7 +16,7 @@ namespace Fig
{
public:
std::size_t id;
FString name;
String name;
enum FnType
{
@@ -53,7 +53,7 @@ namespace Fig
new (&body) Ast::BlockStatement();
}
Function(const FString &_name,
Function(const String &_name,
Ast::FunctionParameters _paras,
TypeInfo _retType,
Ast::BlockStatement _body,
@@ -68,13 +68,16 @@ namespace Fig
type = Normal;
}
Function(const FString &_name, std::function<std::shared_ptr<Object>(const std::vector<std::shared_ptr<Object>> &)> fn, int argc) :
Function(const String &_name,
std::function<std::shared_ptr<Object>(const std::vector<std::shared_ptr<Object>> &)> fn,
int argc) :
id(nextId()), name(_name), type(Builtin), builtin(fn), builtinParamCount(argc)
{
type = Builtin;
}
Function(const FString &_name, std::function<std::shared_ptr<Object>(std::shared_ptr<Object>,
Function(const String &_name,
std::function<std::shared_ptr<Object>(std::shared_ptr<Object>,
const std::vector<std::shared_ptr<Object>> &)> fn,
int argc) :
id(nextId()), name(_name), type(MemberType), mtFn(fn), builtinParamCount(argc)

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Context/context_forward.hpp>
@@ -8,20 +8,13 @@ namespace Fig
{
struct Module
{
FString name;
String name;
ContextPtr ctx;
Module() = default;
Module(FString n, ContextPtr c) :
name(std::move(n)),
ctx(std::move(c))
{
}
Module(String n, ContextPtr c) : name(std::move(n)), ctx(std::move(c)) {}
bool operator==(const Module &o) const noexcept
{
return name == o.name;
}
bool operator==(const Module &o) const noexcept { return name == o.name; }
};
};
}; // namespace Fig

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Ast/Statements/StructDefSt.hpp>
#include <Evaluator/Value/Type.hpp>
@@ -14,21 +14,17 @@ namespace Fig
struct Field
{
AccessModifier am;
FString name;
String name;
TypeInfo type;
Ast::Expression defaultValue;
Field(AccessModifier _am, FString _name, TypeInfo _type, Ast::Expression _defaultValue) :
am(_am), name(std::move(_name)), type(std::move(_type)), defaultValue(std::move(_defaultValue)) {}
Field(AccessModifier _am, String _name, TypeInfo _type, Ast::Expression _defaultValue) :
am(_am), name(std::move(_name)), type(std::move(_type)), defaultValue(std::move(_defaultValue))
{
}
bool isPublic() const
{
return am == AccessModifier::Public || am == AccessModifier::PublicConst;
}
bool isConst() const
{
return am == AccessModifier::Const || am == AccessModifier::PublicConst;
}
bool isPublic() const { return am == AccessModifier::Public || am == AccessModifier::PublicConst; }
bool isConst() const { return am == AccessModifier::Const || am == AccessModifier::PublicConst; }
};
struct StructType
@@ -41,7 +37,9 @@ namespace Fig
// ===== Constructors =====
StructType(TypeInfo _type, ContextPtr _defContext, std::vector<Field> _fields, bool _builtin = false) :
type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)), builtin(_builtin) {}
type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)), builtin(_builtin)
{
}
StructType(const StructType &other) = default;
StructType(StructType &&) noexcept = default;
@@ -49,14 +47,8 @@ namespace Fig
StructType &operator=(StructType &&) noexcept = default;
// ===== Comparison =====
bool operator==(const StructType &other) const noexcept
{
return type == other.type;
}
bool operator!=(const StructType &other) const noexcept
{
return !(*this == other);
}
bool operator==(const StructType &other) const noexcept { return type == other.type; }
bool operator!=(const StructType &other) const noexcept { return !(*this == other); }
private:
static std::size_t nextId()
@@ -72,9 +64,6 @@ namespace std
template <>
struct hash<Fig::Field>
{
size_t operator()(const Fig::Field &f)
{
return std::hash<Fig::FString>{}(f.name);
}
size_t operator()(const Fig::Field &f) { return std::hash<Fig::String>{}(f.name); }
};
}; // namespace std

View File

@@ -11,10 +11,10 @@ namespace Fig
{
TypeInfo::TypeInfo() : // only allow use in evaluate time !! <---- dynamic type system requirement
id(1), name(FString(u8"Any"))
id(1), name(String(U"Any"))
{
}
TypeInfo::TypeInfo(const FString &_name, bool reg)
TypeInfo::TypeInfo(const String &_name, bool reg)
{
static size_t id_count = 0;
name = _name;
@@ -28,7 +28,7 @@ namespace Fig
{
if (!getTypeMap().contains(_name))
{
throw RuntimeError(FString(std::format("No type named '{}'", _name.toBasicString())));
throw RuntimeError(String(std::format("No type named '{}'", _name.toBasicString())));
// *this = ValueType::String;
}
id = getTypeMap().at(name); // may throw
@@ -93,25 +93,29 @@ namespace Fig
if (t == ValueType::StructInstance) return obj->as<StructInstance>().parentType;
return t;
}
FString prettyType(std::shared_ptr<const Object> obj)
String prettyType(std::shared_ptr<const Object> obj)
{
return actualType(obj).toString();
}
const TypeInfo ValueType::Any(FString(u8"Any"), true); // id: 1
const TypeInfo ValueType::Null(FString(u8"Null"), true); // id: 2
const TypeInfo ValueType::Int(FString(u8"Int"), true); // id: 3
const TypeInfo ValueType::String(FString(u8"String"), true); // id: 4
const TypeInfo ValueType::Bool(FString(u8"Bool"), true); // id: 5
const TypeInfo ValueType::Double(FString(u8"Double"), true); // id: 6
const TypeInfo ValueType::Function(FString(u8"Function"), true); // id: 7
const TypeInfo ValueType::StructType(FString(u8"StructType"), true); // id: 8
const TypeInfo ValueType::StructInstance(FString(u8"StructInstance"), true); // id: 9
const TypeInfo ValueType::List(FString(u8"List"), true); // id: 10
const TypeInfo ValueType::Map(FString(u8"Map"), true); // id: 11
const TypeInfo ValueType::Module(FString(u8"Module"), true); // id: 12
const TypeInfo ValueType::InterfaceType(FString(u8"InterfaceType"), true); // id: 13
const TypeInfo ValueType::Any(U"Any", true); // id: 1
const TypeInfo ValueType::Null(U"Null", true); // id: 2
const TypeInfo ValueType::Int(U"Int", true); // id: 3
const TypeInfo ValueType::String(U"String", true); // id: 4
const TypeInfo ValueType::Bool(U"Bool", true); // id: 5
const TypeInfo ValueType::Double(U"Double", true); // id: 6
const TypeInfo ValueType::Function(U"Function", true); // id: 7
const TypeInfo ValueType::StructType(U"StructType", true); // id: 8
const TypeInfo ValueType::StructInstance(U"StructInstance", true); // id: 9
const TypeInfo ValueType::List(U"List", true); // id: 10
const TypeInfo ValueType::Map(U"Map", true); // id: 11
const TypeInfo ValueType::Module(U"Module", true); // id: 12
const TypeInfo ValueType::InterfaceType(U"InterfaceType", true); // id: 13
namespace ValueType
{
};
bool implements(const TypeInfo &structType, const TypeInfo &interfaceType, ContextPtr ctx)
{
return ctx->hasImplRegisted(structType, interfaceType);

View File

@@ -1,5 +1,5 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/function.hpp>
#include <Evaluator/Value/interface.hpp>
#include <Evaluator/Value/structType.hpp>
@@ -43,7 +43,7 @@ namespace Fig
}
TypeInfo actualType(std::shared_ptr<const Object> obj);
FString prettyType(std::shared_ptr<const Object> obj);
String prettyType(std::shared_ptr<const Object> obj);
bool operator==(const Object &, const Object &);
@@ -93,89 +93,92 @@ namespace Fig
Module,
InterfaceType>;
static std::unordered_map<TypeInfo, std::unordered_map<FString, BuiltinTypeMemberFn>, TypeInfoHash>
static std::unordered_map<TypeInfo, std::unordered_map<String, BuiltinTypeMemberFn>, TypeInfoHash>
getMemberTypeFunctions()
{
static const std::unordered_map<TypeInfo, std::unordered_map<FString, BuiltinTypeMemberFn>, TypeInfoHash>
static const std::unordered_map<TypeInfo, std::unordered_map<String, BuiltinTypeMemberFn>, TypeInfoHash>
memberTypeFunctions{
{ValueType::Null, {}},
{ValueType::Int, {}},
{ValueType::Double, {}},
{ValueType::String,
{
{u8"length",
{U"length",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 0)
throw RuntimeError(
FString(std::format("`length` expects 0 arguments, {} got", args.size())));
const FString &str = object->as<ValueType::StringClass>();
String(std::format("`length` expects 0 arguments, {} got", args.size())));
const String &str = object->as<ValueType::StringClass>();
return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length()));
}},
{u8"replace",
{U"replace",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2)
throw RuntimeError(
FString(std::format("`replace` expects 2 arguments, {} got", args.size())));
FString &str = object->as<ValueType::StringClass>();
String(std::format("`replace` expects 2 arguments, {} got", args.size())));
String &str = object->as<ValueType::StringClass>();
ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>())
{
throw RuntimeError(FString("`replace` arg 1 expects type Int"));
throw RuntimeError(String("`replace` arg 1 expects type Int"));
}
if (!arg2->is<ValueType::StringClass>())
{
throw RuntimeError(FString("`replace` arg 2 expects type String"));
throw RuntimeError(String("`replace` arg 2 expects type String"));
}
str.realReplace(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::StringClass>());
const String &target = arg2->as<ValueType::StringClass>();
str.replace(arg1->as<ValueType::IntClass>(), target.length(), target);
return Object::getNullInstance();
}},
{u8"erase",
{U"erase",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2)
throw RuntimeError(
FString(std::format("`erase` expects 2 arguments, {} got", args.size())));
FString &str = object->as<ValueType::StringClass>();
String(std::format("`erase` expects 2 arguments, {} got", args.size())));
String &str = object->as<ValueType::StringClass>();
ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>())
{
throw RuntimeError(FString("`erase` arg 1 expects type Int"));
throw RuntimeError(String("`erase` arg 1 expects type Int"));
}
if (!arg2->is<ValueType::IntClass>())
{
throw RuntimeError(FString("`erase` arg 2 expects type Int"));
throw RuntimeError(String("`erase` arg 2 expects type Int"));
}
ValueType::IntClass index = arg1->as<ValueType::IntClass>();
ValueType::IntClass n = arg2->as<ValueType::IntClass>();
if (index < 0 || n < 0)
{
throw RuntimeError(FString("`erase`: index and n must greater or equal to 0"));
throw RuntimeError(String("`erase`: index and n must greater or equal to 0"));
}
if (index + n > str.length())
{
throw RuntimeError(FString("`erase`: length is not long enough to erase"));
throw RuntimeError(String("`erase`: length is not long enough to erase"));
}
str.realErase(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::IntClass>());
str.erase(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::IntClass>());
return Object::getNullInstance();
}},
{u8"insert",
{U"insert",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2)
throw RuntimeError(
FString(std::format("`insert` expects 2 arguments, {} got", args.size())));
FString &str = object->as<ValueType::StringClass>();
String(std::format("`insert` expects 2 arguments, {} got", args.size())));
String &str = object->as<ValueType::StringClass>();
ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>())
{
throw RuntimeError(FString("`insert` arg 1 expects type Int"));
throw RuntimeError(String("`insert` arg 1 expects type Int"));
}
if (!arg2->is<ValueType::StringClass>())
{
throw RuntimeError(FString("`insert` arg 2 expects type String"));
throw RuntimeError(String("`insert` arg 2 expects type String"));
}
str.realInsert(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::StringClass>());
ValueType::IntClass dest = arg1->as<ValueType::IntClass>();
const String &src = arg2->as<ValueType::StringClass>();
str.insert(dest, src);
return Object::getNullInstance();
}},
}},
@@ -184,34 +187,34 @@ namespace Fig
{ValueType::StructInstance, {}},
{ValueType::List,
{
{u8"length",
{U"length",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 0)
throw RuntimeError(
FString(std::format("`length` expects 0 arguments, {} got", args.size())));
String(std::format("`length` expects 0 arguments, {} got", args.size())));
const List &list = object->as<List>();
return std::make_shared<Object>(static_cast<ValueType::IntClass>(list.size()));
}},
{u8"get",
{U"get",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1)
throw RuntimeError(
FString(std::format("`get` expects 1 arguments, {} got", args.size())));
String(std::format("`get` expects 1 arguments, {} got", args.size())));
ObjectPtr arg = args[0];
if (arg->getTypeInfo() != ValueType::Int)
throw RuntimeError(
FString(std::format("`get` argument 1 expects Int, {} got",
arg->getTypeInfo().toString().toBasicString())));
String(std::format("`get` argument 1 expects Int, {} got",
arg->getTypeInfo().toString().toBasicString())));
ValueType::IntClass i = arg->as<ValueType::IntClass>();
const List &list = object->as<List>();
if (i >= list.size()) return Object::getNullInstance();
return list[i].value;
}},
{u8"push",
{U"push",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1)
throw RuntimeError(
FString(std::format("`push` expects 1 arguments, {} got", args.size())));
String(std::format("`push` expects 1 arguments, {} got", args.size())));
ObjectPtr arg = args[0];
List &list = object->as<List>();
list.push_back(arg);
@@ -220,21 +223,21 @@ namespace Fig
}},
{ValueType::Map,
{
{u8"get",
{U"get",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1)
throw RuntimeError(
FString(std::format("`get` expects 1 arguments, {} got", args.size())));
String(std::format("`get` expects 1 arguments, {} got", args.size())));
ObjectPtr index = args[0];
const Map &map = object->as<Map>();
if (!map.contains(index)) return Object::getNullInstance();
return map.at(index);
}},
{u8"contains",
{U"contains",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1)
throw RuntimeError(
FString(std::format("`contains` expects 1 arguments, {} got", args.size())));
String(std::format("`contains` expects 1 arguments, {} got", args.size())));
ObjectPtr index = args[0];
const Map &map = object->as<Map>();
return std::make_shared<Object>(map.contains(index));
@@ -246,29 +249,28 @@ namespace Fig
return memberTypeFunctions;
}
static std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash>
getMemberTypeFunctionsParas()
static std::unordered_map<TypeInfo, std::unordered_map<String, int>, TypeInfoHash> getMemberTypeFunctionsParas()
{
static const std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash>
static const std::unordered_map<TypeInfo, std::unordered_map<String, int>, TypeInfoHash>
memberTypeFunctionsParas{
{ValueType::Null, {}},
{ValueType::Int, {}},
{ValueType::Double, {}},
{ValueType::String,
{
{u8"length", 0},
{u8"replace", 2},
{u8"erase", 2},
{u8"insert", 2},
{U"length", 0},
{U"replace", 2},
{U"erase", 2},
{U"insert", 2},
}},
{ValueType::Function, {}},
{ValueType::StructType, {}},
{ValueType::StructInstance, {}},
{ValueType::List, {{u8"length", 0}, {u8"get", 1}, {u8"push", 1}}},
{ValueType::List, {{U"length", 0}, {U"get", 1}, {U"push", 1}}},
{ValueType::Map,
{
{u8"get", 1},
{u8"contains", 1},
{U"get", 1},
{U"contains", 1},
}},
{ValueType::Module, {}},
{ValueType::InterfaceType, {}},
@@ -276,15 +278,15 @@ namespace Fig
return memberTypeFunctionsParas;
}
bool hasMemberFunction(const FString &name) const
bool hasMemberFunction(const String &name) const
{
return getMemberTypeFunctions().at(getTypeInfo()).contains(name);
}
BuiltinTypeMemberFn getMemberFunction(const FString &name) const
BuiltinTypeMemberFn getMemberFunction(const String &name) const
{
return getMemberTypeFunctions().at(getTypeInfo()).at(name);
}
int getMemberFunctionParaCount(const FString &name) const
int getMemberFunctionParaCount(const String &name) const
{
return getMemberTypeFunctionsParas().at(getTypeInfo()).at(name);
}
@@ -317,7 +319,7 @@ namespace Fig
else if (ti == ValueType::Double)
return Object(ValueType::DoubleClass(0.0));
else if (ti == ValueType::String)
return Object(ValueType::StringClass(u8""));
return Object(ValueType::StringClass(U""));
else if (ti == ValueType::Bool)
return Object(ValueType::BoolClass(false));
else if (ti == ValueType::List)
@@ -420,83 +422,83 @@ namespace Fig
else if (is<ValueType::DoubleClass>())
return as<ValueType::DoubleClass>();
else
throw RuntimeError(u8"getNumericValue: Not a numeric value");
throw RuntimeError(U"getNumericValue: Not a numeric value");
}
FString toStringIO() const
String toStringIO() const
{
if (is<ValueType::StringClass>()) return as<ValueType::StringClass>();
return toString();
}
FString toString(std::unordered_set<const Object *> &visited) const
String toString(std::unordered_set<const Object *> &visited) const
{
if (is<ValueType::NullClass>()) return FString(u8"null");
if (is<ValueType::IntClass>()) return FString(std::to_string(as<ValueType::IntClass>()));
if (is<ValueType::DoubleClass>()) return FString(std::format("{}", as<ValueType::DoubleClass>()));
if (is<ValueType::StringClass>()) return FString(u8"\"" + as<ValueType::StringClass>() + u8"\"");
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? FString(u8"true") : FString(u8"false");
if (is<ValueType::NullClass>()) return String(U"null");
if (is<ValueType::IntClass>()) return String(std::to_string(as<ValueType::IntClass>()));
if (is<ValueType::DoubleClass>()) return String(std::format("{}", as<ValueType::DoubleClass>()));
if (is<ValueType::StringClass>()) return String(String(U"\"") + as<ValueType::StringClass>() + String(U"\""));
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? String(U"true") : String(U"false");
if (is<Function>())
return FString(std::format(
return String(std::format(
"<Function '{}' at {:p}>", as<Function>().id, static_cast<const void *>(&as<Function>())));
if (is<StructType>())
return FString(std::format("<StructType '{}' at {:p}>",
as<StructType>().type.toString().toBasicString(),
static_cast<const void *>(&as<StructType>())));
return String(std::format("<StructType '{}' at {:p}>",
as<StructType>().type.toString().toBasicString(),
static_cast<const void *>(&as<StructType>())));
if (is<StructInstance>())
return FString(std::format("<StructInstance '{}' at {:p}>",
as<StructInstance>().parentType.toString().toBasicString(),
static_cast<const void *>(&as<StructInstance>())));
return String(std::format("<StructInstance '{}' at {:p}>",
as<StructInstance>().parentType.toString().toBasicString(),
static_cast<const void *>(&as<StructInstance>())));
if (is<List>())
{
if (visited.contains(this)) { return u8"[...]"; }
if (visited.contains(this)) { return U"[...]"; }
visited.insert(this);
FString output(u8"[");
String output(U"[");
const List &list = as<List>();
bool first_flag = true;
for (auto &ele : list)
{
if (!first_flag) output += u8", ";
if (!first_flag) output += U", ";
output += ele.value->toString(visited);
first_flag = false;
}
output += u8"]";
output += U"]";
return output;
}
if (is<Map>())
{
if (visited.contains(this)) { return u8"{...}"; }
if (visited.contains(this)) { return U"{...}"; }
visited.insert(this);
FString output(u8"{");
String output(U"{");
const Map &map = as<Map>();
bool first_flag = true;
for (auto &[key, value] : map)
{
if (!first_flag) output += u8", ";
output += key.value->toString(visited) + FString(u8" : ") + value->toString(visited);
if (!first_flag) output += U", ";
output += key.value->toString(visited) + String(U" : ") + value->toString(visited);
first_flag = false;
}
output += u8"}";
output += U"}";
return output;
}
if (is<Module>())
{
return FString(std::format("<Module '{}' at {:p}>",
as<Module>().name.toBasicString(),
static_cast<const void *>(&as<Module>())));
return String(std::format("<Module '{}' at {:p}>",
as<Module>().name.toBasicString(),
static_cast<const void *>(&as<Module>())));
}
if (is<InterfaceType>())
{
return FString(std::format("<InterfaceType '{}' at {:p}>",
as<InterfaceType>().type.toString().toBasicString(),
static_cast<const void *>(&as<InterfaceType>())));
return String(std::format("<InterfaceType '{}' at {:p}>",
as<InterfaceType>().type.toString().toBasicString(),
static_cast<const void *>(&as<InterfaceType>())));
}
return FString(u8"<error>");
return String(U"<error>");
}
FString toString() const
String toString() const
{
std::unordered_set<const Object *> visited{};
return toString(visited);
@@ -516,7 +518,7 @@ namespace Fig
friend Object operator+(const Object &lhs, const Object &rhs)
{
if (lhs.isNull() || rhs.isNull())
throw ValueError(FString(makeTypeErrorMessage("Cannot add", "+", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Cannot add", "+", lhs, rhs)));
if (lhs.isNumeric() && rhs.isNumeric())
{
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
@@ -525,14 +527,14 @@ namespace Fig
return Object(result);
}
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
return Object(FString(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>()));
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "+", lhs, rhs)));
return Object(String(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>()));
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "+", lhs, rhs)));
}
friend Object operator-(const Object &lhs, const Object &rhs)
{
if (lhs.isNull() || rhs.isNull())
throw ValueError(FString(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs)));
if (lhs.isNumeric() && rhs.isNumeric())
{
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
@@ -540,13 +542,13 @@ namespace Fig
if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
return Object(result);
}
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs)));
}
friend Object operator*(const Object &lhs, const Object &rhs)
{
if (lhs.isNull() || rhs.isNull())
throw ValueError(FString(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs)));
if (lhs.isNumeric() && rhs.isNumeric())
{
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
@@ -556,22 +558,22 @@ namespace Fig
}
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::IntClass>())
{
FString result;
const FString &l = lhs.as<ValueType::StringClass>();
String result;
const String &l = lhs.as<ValueType::StringClass>();
for (size_t i = 0; i < rhs.getNumericValue(); ++i) { result += l; }
return Object(result);
}
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs)));
}
friend Object operator/(const Object &lhs, const Object &rhs)
{
if (lhs.isNull() || rhs.isNull())
throw ValueError(FString(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs)));
if (lhs.isNumeric() && rhs.isNumeric())
{
auto rnv = rhs.getNumericValue();
if (rnv == 0) throw ValueError(FString(makeTypeErrorMessage("Division by zero", "/", lhs, rhs)));
if (rnv == 0) throw ValueError(String(makeTypeErrorMessage("Division by zero", "/", lhs, rhs)));
// bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
auto result = lhs.getNumericValue() / rnv;
// if (bothInt)
@@ -581,18 +583,18 @@ namespace Fig
// DO NOT convert it to INT
return Object(result);
}
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs)));
}
friend Object operator%(const Object &lhs, const Object &rhs)
{
if (lhs.isNull() || rhs.isNull())
throw ValueError(FString(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs)));
if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
{
ValueType::IntClass lv = lhs.as<ValueType::IntClass>();
ValueType::IntClass rv = lhs.as<ValueType::IntClass>();
if (rv == 0) throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
if (rv == 0) throw ValueError(String(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
ValueType::IntClass q = lv / rv;
ValueType::IntClass r = lv % rv;
@@ -603,25 +605,25 @@ namespace Fig
if (lhs.isNumeric() && rhs.isNumeric())
{
auto rnv = rhs.getNumericValue();
if (rnv == 0) throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
if (rnv == 0) throw ValueError(String(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
auto result = std::fmod(lhs.getNumericValue(), rnv);
return Object(result);
}
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
}
// logic
friend Object operator&&(const Object &lhs, const Object &rhs)
{
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>())
throw ValueError(FString(makeTypeErrorMessage("Logical AND requires bool", "&&", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Logical AND requires bool", "&&", lhs, rhs)));
return Object(lhs.as<ValueType::BoolClass>() && rhs.as<ValueType::BoolClass>());
}
friend Object operator||(const Object &lhs, const Object &rhs)
{
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>())
throw ValueError(FString(makeTypeErrorMessage("Logical OR requires bool", "||", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Logical OR requires bool", "||", lhs, rhs)));
return Object(lhs.as<ValueType::BoolClass>() || rhs.as<ValueType::BoolClass>());
}
@@ -629,29 +631,30 @@ namespace Fig
{
if (!v.is<ValueType::BoolClass>())
throw ValueError(
FString(std::format("Logical NOT requires bool: '{}'", v.getTypeInfo().name.toBasicString())));
String(std::format("Logical NOT requires bool: '{}'", v.getTypeInfo().name.toBasicString())));
return Object(!v.as<ValueType::BoolClass>());
}
friend Object operator-(const Object &v)
{
if (v.isNull()) throw ValueError(FString(u8"Unary minus cannot be applied to null"));
if (v.isNull()) throw ValueError(String(U"Unary minus cannot be applied to null"));
if (v.is<ValueType::IntClass>()) return Object(-v.as<ValueType::IntClass>());
if (v.is<ValueType::DoubleClass>()) return Object(-v.as<ValueType::DoubleClass>());
throw ValueError(
FString(std::format("Unary minus requires int or double: '{}'", v.getTypeInfo().name.toBasicString())));
String(std::format("Unary minus requires int or double: '{}'", v.getTypeInfo().name.toBasicString())));
}
friend Object operator~(const Object &v)
{
if (!v.is<ValueType::IntClass>())
throw ValueError(
FString(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
String(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
return Object(~v.as<ValueType::IntClass>());
}
// comparison
friend bool operator==(const Object &lhs, const Object &rhs) {
friend bool operator==(const Object &lhs, const Object &rhs)
{
if (lhs.isNumeric() && rhs.isNumeric())
{
return nearlyEqual(lhs.getNumericValue(), rhs.getNumericValue());
@@ -664,7 +667,7 @@ namespace Fig
if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() < rhs.getNumericValue();
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
return lhs.as<ValueType::StringClass>() < rhs.as<ValueType::StringClass>();
throw ValueError(FString(makeTypeErrorMessage("Unsupported comparison", "<", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Unsupported comparison", "<", lhs, rhs)));
}
friend bool operator<=(const Object &lhs, const Object &rhs) { return lhs == rhs || lhs < rhs; }
friend bool operator>(const Object &lhs, const Object &rhs)
@@ -672,7 +675,7 @@ namespace Fig
if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() > rhs.getNumericValue();
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
return lhs.as<ValueType::StringClass>() > rhs.as<ValueType::StringClass>();
throw ValueError(FString(makeTypeErrorMessage("Unsupported comparison", ">", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Unsupported comparison", ">", lhs, rhs)));
}
friend bool operator>=(const Object &lhs, const Object &rhs) { return lhs == rhs || lhs > rhs; }
@@ -680,21 +683,21 @@ namespace Fig
friend Object bit_and(const Object &lhs, const Object &rhs)
{
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
throw ValueError(FString(makeTypeErrorMessage("Bitwise AND requires int", "&", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Bitwise AND requires int", "&", lhs, rhs)));
return Object(lhs.as<ValueType::IntClass>() & rhs.as<ValueType::IntClass>());
}
friend Object bit_or(const Object &lhs, const Object &rhs)
{
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
throw ValueError(FString(makeTypeErrorMessage("Bitwise OR requires int", "|", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Bitwise OR requires int", "|", lhs, rhs)));
return Object(lhs.as<ValueType::IntClass>() | rhs.as<ValueType::IntClass>());
}
friend Object bit_xor(const Object &lhs, const Object &rhs)
{
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
throw ValueError(FString(makeTypeErrorMessage("Bitwise XOR requires int", "^", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Bitwise XOR requires int", "^", lhs, rhs)));
return Object(lhs.as<ValueType::IntClass>() ^ rhs.as<ValueType::IntClass>());
}
@@ -702,28 +705,28 @@ namespace Fig
{
if (!v.is<ValueType::IntClass>())
throw ValueError(
FString(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
String(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
return Object(~v.as<ValueType::IntClass>());
}
friend Object shift_left(const Object &lhs, const Object &rhs)
{
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
throw ValueError(FString(makeTypeErrorMessage("Shift left requires int", "<<", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Shift left requires int", "<<", lhs, rhs)));
return Object(lhs.as<ValueType::IntClass>() << rhs.as<ValueType::IntClass>());
}
friend Object shift_right(const Object &lhs, const Object &rhs)
{
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
throw ValueError(FString(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs)));
throw ValueError(String(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs)));
return Object(lhs.as<ValueType::IntClass>() >> rhs.as<ValueType::IntClass>());
}
friend Object power(const Object &base, const Object &exp)
{
if (base.isNull() || exp.isNull())
throw ValueError(FString(makeTypeErrorMessage("Cannot exponentiate", "**", base, exp)));
throw ValueError(String(makeTypeErrorMessage("Cannot exponentiate", "**", base, exp)));
if (base.isNumeric() && exp.isNumeric())
{
bool bothInt = base.is<ValueType::IntClass>() && exp.is<ValueType::IntClass>();
@@ -731,7 +734,7 @@ namespace Fig
if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
return Object(result);
}
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "**", base, exp)));
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "**", base, exp)));
}
};

View File

@@ -8,10 +8,13 @@ namespace Fig
{
public:
using UnaddressableError::UnaddressableError;
virtual FString toString() const override
virtual String toString() const override
{
std::string msg = std::format("[ValueError] {} in [{}] {}", std::string(this->message.begin(), this->message.end()), this->src_loc.file_name(), this->src_loc.function_name());
return FString(msg);
std::string msg = std::format("[ValueError] {} in [{}] {}",
std::string(this->message.begin(), this->message.end()),
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
}
};
};
}; // namespace Fig

View File

@@ -9,7 +9,7 @@
#include <Evaluator/Value/Type.hpp>
#include <Evaluator/Value/structInstance.hpp>
#include <Ast/astBase.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Core/StatementResult.hpp>
#include <Evaluator/Value/value.hpp>
#include <Error/errorLog.hpp>
@@ -50,16 +50,16 @@ namespace Fig
ContextPtr Evaluator::loadModule(const std::filesystem::path &path)
{
static std::unordered_map<FString, std::pair<std::vector<FString>, std::vector<Ast::AstBase>>> mod_ast_cache{};
static std::unordered_map<String, std::pair<std::vector<String>, std::vector<Ast::AstBase>>> mod_ast_cache{};
FString modSourcePath(path.string());
String modSourcePath(path.string());
std::ifstream file(path);
assert(file.is_open());
std::vector<Ast::AstBase> asts;
std::vector<FString> modSourceLines;
std::vector<String> modSourceLines;
if (mod_ast_cache.contains(modSourcePath))
{
@@ -72,9 +72,9 @@ namespace Fig
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
modSourceLines = Utils::splitSource(FString(source));
modSourceLines = Utils::splitSource(String(source));
Lexer lexer((FString(source)), modSourcePath, modSourceLines);
Lexer lexer((String(source)), modSourcePath, modSourceLines);
Parser parser(lexer, modSourcePath, modSourceLines);
asts = parser.parseAll();
@@ -85,7 +85,7 @@ namespace Fig
evaluator.SetSourcePath(modSourcePath);
evaluator.SetSourceLines(modSourceLines);
ContextPtr modctx = std::make_shared<Context>(FString(std::format("<Module at {}>", path.string())), nullptr);
ContextPtr modctx = std::make_shared<Context>(String(std::format("<Module at {}>", path.string())), nullptr);
evaluator.SetGlobalContext(modctx);
evaluator.RegisterBuiltinsValue();
@@ -96,10 +96,10 @@ namespace Fig
StatementResult Evaluator::evalImportSt(Ast::Import i, ContextPtr ctx)
{
const std::vector<FString> &pathVec = i->path;
const std::vector<String> &pathVec = i->path;
FString modName = pathVec.back(); // pathVec at least has 1 element
if (modName == u8"_builtins")
String modName = pathVec.back(); // pathVec at least has 1 element
if (modName == U"\1")
{
RegisterBuiltins();
return StatementResult::normal();
@@ -109,8 +109,7 @@ namespace Fig
if (ctx->containsInThisScope(modName))
{
throw EvaluatorError(
u8"RedeclarationError", std::format("{} has already been declared.", modName.toBasicString()), i);
throw EvaluatorError(U"\1", std::format("{} has already been declared.", modName.toBasicString()), i);
}
auto path = resolveModulePath(pathVec);
@@ -124,7 +123,7 @@ namespace Fig
if (ctx->getOpRegistry().contains(type))
{
throw EvaluatorError(
u8"DuplicateOperationOverload",
U"\1",
std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object",
modCtx->getScopeName().toBasicString(),
ctx->getScopeName().toBasicString(),
@@ -135,7 +134,7 @@ namespace Fig
}
if (!i->names.empty())
{
for (const FString &symName : i->names)
for (const String &symName : i->names)
{
LvObject tmp(modCtx->get(symName), modCtx);
const ObjectPtr &value = tmp.get();
@@ -183,13 +182,13 @@ namespace Fig
*/
const StructInstance &resInst = result->as<StructInstance>();
Function getErrorClassFn = ctx->getImplementedMethod(resultType, u8"getErrorClass");
Function getErrorClassFn = ctx->getImplementedMethod(resultType, U"\1");
getErrorClassFn = Function(getErrorClassFn.name,
getErrorClassFn.paras,
getErrorClassFn.retType,
getErrorClassFn.body,
resInst.localContext);
Function getErrorMessageFn = ctx->getImplementedMethod(resultType, u8"getErrorMessage");
Function getErrorMessageFn = ctx->getImplementedMethod(resultType, U"\1");
getErrorMessageFn = Function(getErrorMessageFn.name,
getErrorMessageFn.paras,
getErrorMessageFn.retType,
@@ -210,17 +209,16 @@ namespace Fig
// std::cerr << errorClassRes.unwrap()->toString().toBasicString() << "\n";
// std::cerr << errorMessageRes.unwrap()->toString().toBasicString() << "\n";
const FString &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>();
const FString &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>();
const String &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>();
const String &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>();
ErrorLog::logFigErrorInterface(errorClass, errorMessage);
std::exit(1);
}
else
{
throw EvaluatorError(u8"UncaughtExceptionError",
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
stmt);
throw EvaluatorError(
U"\1", std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), stmt);
}
}

View File

@@ -34,12 +34,12 @@ namespace Fig
ContextPtr global;
public:
FString sourcePath;
std::vector<FString> sourceLines;
String sourcePath;
std::vector<String> sourceLines;
void SetSourcePath(const FString &sp) { sourcePath = sp; }
void SetSourcePath(const String &sp) { sourcePath = sp; }
void SetSourceLines(const std::vector<FString> &sl) { sourceLines = sl; }
void SetSourceLines(const std::vector<String> &sl) { sourceLines = sl; }
void SetGlobalContext(ContextPtr ctx)
{
@@ -47,7 +47,7 @@ namespace Fig
global = ctx;
}
void CreateGlobalContext() { global = std::make_shared<Context>(FString(u8"<Global>")); }
void CreateGlobalContext() { global = std::make_shared<Context>(String(U"\1")); }
void RegisterBuiltins() // only function
{
@@ -67,33 +67,31 @@ namespace Fig
.interfaceType = Builtins::getErrorInterfaceTypeInfo(),
.structType = Builtins::getTypeErrorStructTypeInfo(),
.implMethods = {
{u8"toString",
Function(
u8"toString",
Ast::FunctionParameters{},
ValueType::String,
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::BinaryExprAst>(
std::make_shared<Ast::ValueExprAst>(std::make_shared<Object>(u8"TypeError: ")),
Ast::Operator::Add,
std::make_shared<Ast::FunctionCallExpr>(
std::make_shared<Ast::VarExprAst>(u8"getErrorMessage"),
Ast::FunctionArguments{})))})),
nullptr)},
{u8"getErrorClass",
Function(u8"getErrorClass",
{U"\1",
Function(U"\1",
Ast::FunctionParameters{},
ValueType::String,
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::BinaryExprAst>(
std::make_shared<Ast::ValueExprAst>(std::make_shared<Object>(U"\1")),
Ast::Operator::Add,
std::make_shared<Ast::FunctionCallExpr>(
std::make_shared<Ast::VarExprAst>(U"\1"), Ast::FunctionArguments{})))})),
nullptr)},
{U"\1",
Function(U"\1",
Ast::FunctionParameters{},
ValueType::String,
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::ValueExprAst>(
std::make_shared<Object>(FString(u8"TypeError"))))})),
std::make_shared<Object>(String(U"\1"))))})),
nullptr)},
{u8"getErrorMessage",
Function(u8"getErrorMessage",
{U"\1",
Function(U"\1",
Ast::FunctionParameters{},
ValueType::String,
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::VarExprAst>(u8"msg"))})),
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::VarExprAst>(U"\1"))})),
nullptr)},
}});
}
@@ -110,13 +108,13 @@ namespace Fig
bool isInterfaceSignatureMatch(const Ast::ImplementMethod &, const Ast::InterfaceMethod &);
ObjectPtr genTypeError(const FString &_msg,
ObjectPtr genTypeError(const String &_msg,
const Ast::AstBase &_ast,
ContextPtr ctx,
std::source_location loc = std::source_location::current())
{
ContextPtr stCtx = std::make_shared<Context>(u8"<TypeError Instance>");
stCtx->def(u8"msg", ValueType::String, AccessModifier::Const, std::make_shared<Object>(_msg));
ContextPtr stCtx = std::make_shared<Context>(U"\1");
stCtx->def(U"\1", ValueType::String, AccessModifier::Const, std::make_shared<Object>(_msg));
return std::make_shared<Object>(StructInstance(Builtins::getTypeErrorStructTypeInfo(), stCtx));
}
@@ -143,7 +141,7 @@ namespace Fig
StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block
StatementResult evalStatement(Ast::Statement, ContextPtr); // statement
std::filesystem::path resolveModulePath(const std::vector<FString> &);
std::filesystem::path resolveModulePath(const std::vector<String> &);
ContextPtr loadModule(const std::filesystem::path &);
StatementResult evalImportSt(Ast::Import, ContextPtr);

View File

@@ -8,16 +8,15 @@ namespace Fig
class EvaluatorError final : public AddressableError
{
public:
FString typeName;
String typeName;
using AddressableError::AddressableError;
EvaluatorError(FString _typeName,
FString msg,
EvaluatorError(String _typeName,
String msg,
Ast::AstBase ast,
std::source_location loc = std::source_location::current())
{
message = msg;
src_loc = std::move(loc);
typeName = std::move(_typeName);
@@ -29,25 +28,24 @@ namespace Fig
sourcePath = *ast->getAAI().sourcePath;
sourceLines = *ast->getAAI().sourceLines;
}
}
EvaluatorError(FString _typeName,
std::string_view msg,
Ast::AstBase ast,
std::source_location loc = std::source_location::current())
{
message = FString::fromBasicString(std::string(msg.data()));
line = ast->getAAI().line;
column = ast->getAAI().column;
// EvaluatorError(String _typeName,
// std::string_view msg,
// Ast::AstBase ast,
// std::source_location loc = std::source_location::current())
// {
// message = String(std::string(msg.data()));
// line = ast->getAAI().line;
// column = ast->getAAI().column;
src_loc = std::move(loc);
// src_loc = std::move(loc);
typeName = std::move(_typeName);
// typeName = std::move(_typeName);
sourcePath = *ast->getAAI().sourcePath;
sourceLines = *ast->getAAI().sourceLines;
}
// sourcePath = *ast->getAAI().sourcePath;
// sourceLines = *ast->getAAI().sourceLines;
// }
virtual FString getErrorType() const override { return typeName; }
virtual String getErrorType() const override { return typeName; }
};
}; // namespace Fig

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <vector>
#include <cstdint>
@@ -51,12 +51,12 @@ namespace Fig::IR
struct Function
{
FString name;
String name;
uint16_t paramCount;
uint16_t localCount; // 不含参数
uint16_t regCount; // param + locals + temps
uint16_t regCount; // param + locals + temps
std::vector<Inst> code;
};
};
}; // namespace Fig::IR

View File

@@ -1,9 +1,9 @@
#include <Core/fig_string.hpp>
#include <Error/error.hpp>
#include <Token/token.hpp>
#include <Lexer/lexer.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Core/CharUtils.hpp>
#include <Utils/utils.hpp>
#if 0
@@ -17,113 +17,110 @@
namespace Fig
{
const std::unordered_map<FString, TokenType> Lexer::symbol_map{
const std::unordered_map<String, TokenType> Lexer::symbol_map{
// 三字符
{FString(u8"..."), TokenType::TripleDot},
{String(U"..."), TokenType::TripleDot},
// 双字符
{FString(u8"=="), TokenType::Equal},
{FString(u8"!="), TokenType::NotEqual},
{FString(u8"<="), TokenType::LessEqual},
{FString(u8">="), TokenType::GreaterEqual},
{FString(u8"<<"), TokenType::ShiftLeft},
{FString(u8">>"), TokenType::ShiftRight},
{FString(u8"+="), TokenType::PlusEqual},
{FString(u8"-="), TokenType::MinusEqual},
{FString(u8"*="), TokenType::AsteriskEqual},
{FString(u8"/="), TokenType::SlashEqual},
{FString(u8"%="), TokenType::PercentEqual},
{FString(u8"^="), TokenType::CaretEqual},
{FString(u8"++"), TokenType::DoublePlus},
{FString(u8"--"), TokenType::DoubleMinus},
{FString(u8"&&"), TokenType::DoubleAmpersand},
{FString(u8"||"), TokenType::DoublePipe},
{FString(u8":="), TokenType::Walrus},
{FString(u8"**"), TokenType::Power},
{FString(u8"->"), TokenType::RightArrow},
{FString(u8"=>"), TokenType::DoubleArrow},
{String(U"=="), TokenType::Equal},
{String(U"!="), TokenType::NotEqual},
{String(U"<="), TokenType::LessEqual},
{String(U">="), TokenType::GreaterEqual},
{String(U"<<"), TokenType::ShiftLeft},
{String(U">>"), TokenType::ShiftRight},
{String(U"+="), TokenType::PlusEqual},
{String(U"-="), TokenType::MinusEqual},
{String(U"*="), TokenType::AsteriskEqual},
{String(U"/="), TokenType::SlashEqual},
{String(U"%="), TokenType::PercentEqual},
{String(U"^="), TokenType::CaretEqual},
{String(U"++"), TokenType::DoublePlus},
{String(U"--"), TokenType::DoubleMinus},
{String(U"&&"), TokenType::DoubleAmpersand},
{String(U"||"), TokenType::DoublePipe},
{String(U":="), TokenType::Walrus},
{String(U"**"), TokenType::Power},
{String(U"->"), TokenType::RightArrow},
{String(U"=>"), TokenType::DoubleArrow},
// 单字符
{FString(u8"+"), TokenType::Plus},
{FString(u8"-"), TokenType::Minus},
{FString(u8"*"), TokenType::Asterisk},
{FString(u8"/"), TokenType::Slash},
{FString(u8"%"), TokenType::Percent},
{FString(u8"^"), TokenType::Caret},
{FString(u8"&"), TokenType::Ampersand},
{FString(u8"|"), TokenType::Pipe},
{FString(u8"~"), TokenType::Tilde},
{FString(u8"="), TokenType::Assign},
{FString(u8"<"), TokenType::Less},
{FString(u8">"), TokenType::Greater},
{FString(u8"."), TokenType::Dot},
{FString(u8","), TokenType::Comma},
{FString(u8":"), TokenType::Colon},
{FString(u8";"), TokenType::Semicolon},
{FString(u8"'"), TokenType::SingleQuote},
{FString(u8"\""), TokenType::DoubleQuote},
{FString(u8"("), TokenType::LeftParen},
{FString(u8")"), TokenType::RightParen},
{FString(u8"["), TokenType::LeftBracket},
{FString(u8"]"), TokenType::RightBracket},
{FString(u8"{"), TokenType::LeftBrace},
{FString(u8"}"), TokenType::RightBrace},
{FString(u8"?"), TokenType::Question},
{FString(u8"!"), TokenType::Not},
{String(U"+"), TokenType::Plus},
{String(U"-"), TokenType::Minus},
{String(U"*"), TokenType::Asterisk},
{String(U"/"), TokenType::Slash},
{String(U"%"), TokenType::Percent},
{String(U"^"), TokenType::Caret},
{String(U"&"), TokenType::Ampersand},
{String(U"|"), TokenType::Pipe},
{String(U"~"), TokenType::Tilde},
{String(U"="), TokenType::Assign},
{String(U"<"), TokenType::Less},
{String(U">"), TokenType::Greater},
{String(U"."), TokenType::Dot},
{String(U","), TokenType::Comma},
{String(U":"), TokenType::Colon},
{String(U";"), TokenType::Semicolon},
{String(U"'"), TokenType::SingleQuote},
{String(U"\""), TokenType::DoubleQuote},
{String(U"("), TokenType::LeftParen},
{String(U")"), TokenType::RightParen},
{String(U"["), TokenType::LeftBracket},
{String(U"]"), TokenType::RightBracket},
{String(U"{"), TokenType::LeftBrace},
{String(U"}"), TokenType::RightBrace},
{String(U"?"), TokenType::Question},
{String(U"!"), TokenType::Not},
};
const std::unordered_map<FString, TokenType> Lexer::keyword_map{
{FString(u8"and"), TokenType::And},
{FString(u8"or"), TokenType::Or},
{FString(u8"not"), TokenType::Not},
{FString(u8"import"), TokenType::Import},
{FString(u8"func"), TokenType::Function},
{FString(u8"var"), TokenType::Variable},
{FString(u8"const"), TokenType::Const},
// {FString(u8"final"), TokenType::Final},
{FString(u8"while"), TokenType::While},
{FString(u8"for"), TokenType::For},
{FString(u8"if"), TokenType::If},
{FString(u8"else"), TokenType::Else},
{FString(u8"new"), TokenType::New},
{FString(u8"struct"), TokenType::Struct},
{FString(u8"interface"), TokenType::Interface},
{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},
{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"as"), TokenType::As},
const std::unordered_map<String, TokenType> Lexer::keyword_map{
{String(U"and"), TokenType::And},
{String(U"or"), TokenType::Or},
{String(U"not"), TokenType::Not},
{String(U"import"), TokenType::Import},
{String(U"func"), TokenType::Function},
{String(U"var"), TokenType::Variable},
{String(U"const"), TokenType::Const},
// {String(U"final"), TokenType::Final},
{String(U"while"), TokenType::While},
{String(U"for"), TokenType::For},
{String(U"if"), TokenType::If},
{String(U"else"), TokenType::Else},
{String(U"new"), TokenType::New},
{String(U"struct"), TokenType::Struct},
{String(U"interface"), TokenType::Interface},
{String(U"impl"), TokenType::Implement},
{String(U"is"), TokenType::Is},
{String(U"public"), TokenType::Public},
{String(U"return"), TokenType::Return},
{String(U"break"), TokenType::Break},
{String(U"continue"), TokenType::Continue},
{String(U"try"), TokenType::Try},
{String(U"catch"), TokenType::Catch},
{String(U"throw"), TokenType::Throw},
{String(U"Finally"), TokenType::Finally},
{String(U"as"), TokenType::As},
// {FString(u8"Null"), TokenType::TypeNull},
// {FString(u8"Int"), TokenType::TypeInt},
// {FString(u8"String"), TokenType::TypeString},
// {FString(u8"Bool"), TokenType::TypeBool},
// {FString(u8"Double"), TokenType::TypeDouble},
// {String(U"Null"), TokenType::TypeNull},
// {String(U"Int"), TokenType::TypeInt},
// {String(U"String"), TokenType::TypeString},
// {String(U"Bool"), TokenType::TypeBool},
// {String(U"Double"), TokenType::TypeDouble},
};
void Lexer::skipLine()
{
while (*it != U'\n' and hasNext())
{
next();
}
while (current() != U'\n' and hasNext()) { next(); }
next(); // skip '\n'
++line;
}
Token Lexer::scanIdentifier()
{
FString identifier;
String identifier;
while (hasNext())
{
UTF8Char c = *it;
if (c.isAlnum() || c == U'_')
char32_t c = current();
if (CharUtils::isAlnum(c) || c == U'_')
{
identifier += c.getString();
identifier += c;
next();
}
else
@@ -131,23 +128,27 @@ namespace Fig
break;
}
}
if (this->keyword_map.contains(identifier))
{
return Token(identifier, this->keyword_map.at(identifier));
}
else if (identifier == u8"true" || identifier == u8"false")
{
return Token(identifier, TokenType::LiteralBool);
}
else if (identifier == u8"null")
if (this->keyword_map.contains(identifier)) { return Token(identifier, this->keyword_map.at(identifier)); }
else if (identifier == U"\1" || identifier == U"\1") { return Token(identifier, TokenType::LiteralBool); }
else if (identifier == U"\1")
{
// null instance
return Token(identifier, TokenType::LiteralNull);
}
if (keyword_map.contains(Utils::toLower(identifier)))
{
pushWarning(1, identifier); // Identifier is too similar to a keyword or a primitive type
}
// const auto &toLower = [](const String &str) -> String
// {
// String res;
// for (auto c : str)
// {
// res += CharUtils::toLower(c);
// }
// return res;
// };
// if (keyword_map.contains(toLower(identifier)))
// {
// pushWarning(1, identifier); // Identifier is too similar to a keyword or a primitive type
// }
if (identifier.length() <= 1)
{
pushWarning(2, identifier); // The identifier is too abstract
@@ -156,12 +157,12 @@ namespace Fig
}
Token Lexer::scanString()
{
FString str;
String str;
bool unterminated = true;
size_t str_start_col = it.column() - 1;
size_t str_start_col = column - 1;
while (hasNext())
{
UTF8Char c = *it;
char32_t c = current();
if (c == U'"' || c == U'\n')
{
next();
@@ -170,74 +171,74 @@ namespace Fig
}
else if (c == U'\\') // c is '\'
{
if (it.isEnd())
if (!hasNext())
{
error = SyntaxError(u8"Unterminated FString", this->line, it.column(), SourceInfo(this));
error = SyntaxError(U"\1", this->line, column, SourceInfo(this));
return IllegalTok;
}
next();
UTF8Char ec = *it;
char32_t ec = current();
if (ec == U'n')
{
next();
str += u8"\n";
str += U"\1";
}
else if (ec == U't')
{
next();
str += u8"\t";
str += U"\1";
}
else if (ec == U'v')
{
next();
str += u8"\v";
str += U"\1";
}
else if (ec == U'b')
{
next();
str += u8"\b";
str += U"\1";
}
else if (ec == U'"')
{
next();
str += u8"\"";
str += U"\1";
}
else if (ec == U'\'')
{
next();
str += u8"'";
str += U"\1";
}
else
{
error = SyntaxError(FString(std::format("Unsupported escape character: {}",
FString(ec.getString()).toBasicString())),
this->line,
it.column(),
SourceInfo(this));
error =
SyntaxError(String(std::format("Unsupported escape character: {}", String(ec).toBasicString())),
this->line,
column,
SourceInfo(this));
return IllegalTok;
}
}
else
{
str += c.getString();
str += c;
next();
}
}
if (unterminated)
{
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
error = SyntaxError(U"Unterminated FString", this->line, str_start_col, SourceInfo(this));
return IllegalTok;
}
return Token(str, TokenType::LiteralString);
}
Token Lexer::scanRawString()
{
FString str;
String str;
bool unterminated = true;
size_t str_start_col = it.column() - 1;
size_t str_start_col = column - 1;
while (hasNext())
{
UTF8Char c = *it;
char32_t c = current();
if (c == U'"' || c == U'\n')
{
next();
@@ -246,27 +247,27 @@ namespace Fig
}
else
{
str += c.getString();
str += c;
next();
}
}
if (unterminated)
{
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
error = SyntaxError(U"Unterminated FString", this->line, str_start_col, SourceInfo(this));
return IllegalTok;
}
return Token(str, TokenType::LiteralString);
}
Token Lexer::scanMultilineString()
{
FString str;
String str;
bool unterminated = true;
uint8_t end = 0;
size_t str_start_col = it.column() - 1;
size_t str_start_col = column - 1;
while (hasNext())
{
UTF8Char c = *it;
char32_t c = current();
if (c == U'"')
{
if (end == 3)
@@ -281,99 +282,99 @@ namespace Fig
}
else if (c == U'\\') // c is '\'
{
if (it.isEnd())
if (!hasNext())
{
error = SyntaxError(u8"Unterminated FString", this->line, it.column(), SourceInfo(this));
error = SyntaxError(U"Unterminated FString", this->line, column, SourceInfo(this));
return IllegalTok;
}
next();
UTF8Char ec = *it;
char32_t ec = current();
if (ec == U'n')
{
next();
str += u8"\n";
str += U"\n";
}
else if (ec == U't')
{
next();
str += u8"\t";
str += U"\t";
}
else if (ec == U'v')
{
next();
str += u8"\v";
str += U"\v";
}
else if (ec == U'b')
{
next();
str += u8"\b";
str += U"\b";
}
else if (ec == U'"')
{
next();
str += u8"\"";
str += U"\"";
}
else if (ec == U'\'')
{
next();
str += u8"'";
str += U"\'";
}
else if (ec == U'\\')
{
next();
str += u8"\\";
str += U"\\";
}
else
{
error = SyntaxError(FString(std::format("Unsupported escape character: {}",
FString(ec.getString()).toBasicString())),
this->line,
it.column(),
SourceInfo(this));
error = SyntaxError(
String(std::format("Unsupported escape character: {}", String(ec).toBasicString())),
this->line,
column,
SourceInfo(this));
return IllegalTok;
}
}
else
{
str += c.getString();
str += c;
}
end = 0;
}
if (unterminated)
{
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
error = SyntaxError(U"\1", this->line, str_start_col, SourceInfo(this));
return IllegalTok;
}
return Token(str, TokenType::LiteralString);
}
Token Lexer::scanNumber()
{
FString numStr;
String numStr;
bool hasPoint = false;
while (hasNext())
{
UTF8Char ch = *it;
char32_t ch = current();
if (ch.isDigit() || ch == U'e')
if (CharUtils::isDigit(ch) || ch == U'e')
{
numStr += ch.getString();
numStr += ch;
next();
}
else if (ch == U'-' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E')))
{
numStr += ch.getString();
numStr += ch;
next();
}
else if (ch == U'+' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E')))
{
numStr += ch.getString();
numStr += ch;
next();
}
else if (ch == U'.' && !hasPoint)
{
hasPoint = true;
numStr += ch.getString();
numStr += ch;
next();
}
else
@@ -385,9 +386,9 @@ namespace Fig
if (numStr.ends_with(U'e'))
{
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
return IllegalTok;
}
@@ -395,7 +396,7 @@ namespace Fig
bool hasDigit = false;
for (auto it = numStr.begin(); it != numStr.end(); ++it)
{
if (isdigit(*it))
if (CharUtils::isDigit(*it))
{
hasDigit = true;
break;
@@ -404,55 +405,55 @@ namespace Fig
if (!hasDigit)
{
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
return IllegalTok;
}
size_t ePos = numStr.find(U'e');
if (ePos != FString::npos)
if (ePos != String::npos)
{
if (ePos == 0)
{
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
return IllegalTok;
}
if (ePos + 1 >= numStr.length())
{
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
return IllegalTok;
}
bool hasDigitAfterE = false;
for (size_t i = ePos + 1; i < numStr.length(); ++i)
{
UTF8Char c = std::u8string(1,numStr[i]);
char32_t c = numStr[i];
if (c == U'+' || c == U'-')
{
if (i != ePos + 1)
{
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
return IllegalTok;
}
continue;
}
if (c.isDigit()) { hasDigitAfterE = true; }
if (CharUtils::isDigit(c)) { hasDigitAfterE = true; }
else
{
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
return IllegalTok;
}
@@ -460,9 +461,9 @@ namespace Fig
if (!hasDigitAfterE)
{
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
return IllegalTok;
}
@@ -472,25 +473,24 @@ namespace Fig
}
Token Lexer::scanSymbol()
{
FString sym;
UTF8Char ch = *it;
sym += ch.getString();
String sym;
char32_t ch = current();
sym += ch;
auto startsWith = [&](const FString &prefix) -> bool {
auto startsWith = [&](const String &prefix) -> bool {
for (const auto &p : symbol_map)
{
const FString &op = p.first;
if (op.starts_with(prefix))
return true;
const String &op = p.first;
if (op.starts_with(prefix)) return true;
}
return false;
};
if (!startsWith(sym))
{
error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())),
error = SyntaxError(String(std::format("No such operator: {}", sym.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
next();
return IllegalTok;
@@ -498,11 +498,10 @@ namespace Fig
while (hasNext())
{
UTF8Char peek = it.peek();
if (!peek.isPunct())
break;
char32_t peek_ch = peek();
if (!CharUtils::isPunct(peek_ch)) break;
FString candidate = sym + FString(peek.getString());
String candidate = sym + peek_ch;
if (startsWith(candidate))
{
@@ -517,9 +516,9 @@ namespace Fig
if (!symbol_map.contains(sym))
{
error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())),
error = SyntaxError(String(std::format("No such operator: {}", sym.toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
next();
return IllegalTok;
@@ -533,37 +532,34 @@ namespace Fig
{
// entry: when iterator current char is '/' and peek is '/' or '*'
// current char is '/'
FString comment;
String comment;
if (it.peek() == U'/') // single-line comment
if (peek() == U'/') // single-line comment
{
next(); // skip first '/'
next(); // skip second '/'
UTF8Char c = *it;
char32_t c = current();
while (c != U'\n' and hasNext())
{
comment += c.getString();
comment += c;
next();
c = *it;
c = current();
}
if (hasNext() && c == U'\n')
{
next();
}
if (hasNext() && c == U'\n') { next(); }
}
else // multi-line comment
{
next(); // skip '/'
next(); // skip '*'
UTF8Char c = *it;
char32_t c = current();
bool terminated = false;
while (hasNext())
{
if (c == U'*' and hasNext() and it.peek() == U'/')
if (c == U'*' and hasNext() and peek() == U'/')
{
next(); // skip '*'
next(); // skip '/'
@@ -572,16 +568,15 @@ namespace Fig
}
else
{
comment += c.getString();
comment += c;
next();
c = *it;
c = current();
}
}
if (!terminated)
{
error =
SyntaxError(FString(u8"Unterminated multiline comment"), this->line, it.column(), SourceInfo(this));
error = SyntaxError(String(U"\1"), this->line, column, SourceInfo(this));
next();
return IllegalTok;
}
@@ -591,76 +586,61 @@ namespace Fig
}
Token Lexer::nextToken()
{
if (!hasNext())
if (!hasNext()) { return EOFTok.setPos(getCurrentLine(), getCurrentColumn()); }
char32_t ch = current();
while (hasNext())
{
return EOFTok;
}
UTF8Char ch = *it;
while (ch.isSpace())
{
next();
ch = *it;
if (!hasNext())
ch = current();
if (!CharUtils::isSpace(ch))
{
return EOFTok.setPos(getCurrentLine(), getCurrentColumn());
break;
}
next();
}
last_line = getCurrentLine();
last_column = getCurrentColumn();
if (ch == U'/')
{
UTF8Char c{u8""};
char32_t c;
if (!hasNext())
{
next();
return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column);
return Token(U"\1", this->symbol_map.at(U"\1")).setPos(last_line, last_column);
}
c = it.peek();
c = peek();
if (c != U'/' and c != U'*')
{
next();
return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column);
return Token(U"\1", this->symbol_map.at(U"\1")).setPos(last_line, last_column);
}
scanComments().setPos(last_line, last_column);
return nextToken();
// now we ignore comments to avoid some stupid bugs
}
if (ch == U'r' and hasNext() and it.peek() == U'"')
if (ch == U'r' and hasNext() and peek() == U'"')
{
// r""
// raw FString
// raw String
next();
next();
return scanRawString().setPos(last_line, last_column);
}
if (ch.isAlpha() || ch == U'_')
{
return scanIdentifier().setPos(last_line, last_column);
}
if (CharUtils::isAlpha(ch) || ch == U'_') { return scanIdentifier().setPos(last_line, last_column); }
else if (ch == U'"')
{
next();
return scanString().setPos(last_line, last_column);
}
else if (ch.isDigit())
{
return scanNumber().setPos(last_line, last_column);
}
else if (ch.isPunct())
{
return scanSymbol().setPos(last_line, last_column);
}
else if (CharUtils::isDigit(ch)) { return scanNumber().setPos(last_line, last_column); }
else if (CharUtils::isPunct(ch)) { return scanSymbol().setPos(last_line, last_column); }
else
{
error =
SyntaxError(FString(std::format("Cannot tokenize char: '{}'", FString(ch.getString()).toBasicString())),
SyntaxError(String(std::format("Cannot tokenize char: '{}'", String(ch).toBasicString())),
this->line,
it.column(),
column,
SourceInfo(this));
if (hasNext())
{
next();
}
if (hasNext()) { next(); }
return IllegalTok.setPos(last_line, last_column);
}
}

View File

@@ -8,8 +8,7 @@
#include <Token/token.hpp>
#include <Error/error.hpp>
#include <Core/fig_string.hpp>
#include <Core/utf8_iterator.hpp>
#include <Core/String.hpp>
#include <Core/warning.hpp>
namespace Fig
@@ -19,26 +18,33 @@ namespace Fig
{
private:
size_t line;
const FString source;
const String source;
SyntaxError error;
UTF8Iterator it;
FString sourcePath;
std::vector<FString> sourceLines;
String sourcePath;
std::vector<String> sourceLines;
std::vector<Warning> warnings;
int64_t idx = 0;
size_t last_line, last_column, column = 1;
bool hasNext()
{
return !this->it.isEnd();
char32_t current() const { return source[idx]; }
char32_t peek() const {
if (idx + 1 >= source.length())
{
return U'\0';
}
return source[idx + 1];
}
bool hasNext() { return idx < source.length(); }
void skipLine();
inline void next()
{
if (*it == U'\n')
if (current() == U'\n')
{
++this->line;
this->column = 1;
@@ -47,43 +53,31 @@ namespace Fig
{
++this->column;
}
++it;
++idx;
}
void pushWarning(size_t id, FString msg)
void pushWarning(size_t id, String msg)
{
warnings.push_back(Warning(id, std::move(msg), getCurrentLine(), getCurrentColumn()));
}
void pushWarning(size_t id, FString msg, size_t line, size_t column)
void pushWarning(size_t id, String msg, size_t line, size_t column)
{
warnings.push_back(Warning(id, std::move(msg), line, column));
}
public:
static const std::unordered_map<FString, TokenType> symbol_map;
static const std::unordered_map<FString, TokenType> keyword_map;
static const std::unordered_map<String, TokenType> symbol_map;
static const std::unordered_map<String, TokenType> keyword_map;
inline Lexer(const FString &_source, const FString &_sourcePath, const std::vector<FString> &_sourceLines) :
source(_source), it(source), sourcePath(_sourcePath), sourceLines(_sourceLines)
inline Lexer(const String &_source, const String &_sourcePath, const std::vector<String> &_sourceLines) :
source(_source), sourcePath(_sourcePath), sourceLines(_sourceLines)
{
line = 1;
}
inline size_t getCurrentLine()
{
return line;
}
inline size_t getCurrentColumn()
{
return column;
}
SyntaxError getError() const
{
return error;
}
std::vector<Warning> getWarnings() const
{
return warnings;
}
inline size_t getCurrentLine() { return line; }
inline size_t getCurrentColumn() { return column; }
SyntaxError getError() const { return error; }
std::vector<Warning> getWarnings() const { return warnings; }
Token nextToken();
Token scanNumber();

View File

@@ -5,7 +5,7 @@
Copyright © 2025 PuqiAR. All rights reserved.
*/
import std.value; // `type` function and string_from
// import std.value; // `type` function and string_from
struct FormatError
@@ -37,7 +37,7 @@ public func format(objects ...) -> Any
}
var fmt := objects[0];
var fmtType := value.type(fmt);
var fmtType := type(fmt);
if fmtType != "String"
{
throw new FormatError{"arg 0 (fmt) must be String type, got " + fmtType};
@@ -88,7 +88,7 @@ public func format(objects ...) -> Any
throw new FormatError{"require enough format expression"};
}
result += value.string_from(objects[argIndex]);
result += objects[argIndex] as String;
argIndex += 1;
i = endIndex + 1;
@@ -116,7 +116,7 @@ public func format(objects ...) -> Any
public func formatByListArgs(objects) -> Any
{
if value.type(objects) != "List"
if not (objects is List)
{
return null;
}
@@ -126,7 +126,7 @@ if objects.length() < 1
}
var fmt := objects[0];
var fmtType := value.type(fmt);
var fmtType := type(fmt);
if fmtType != "String"
{
throw new FormatError{"arg 0 (fmt) must be String type, got " + fmtType};
@@ -177,7 +177,7 @@ if objects.length() < 1
throw new FormatError{"require enough format expression"};
}
result += value.string_from(objects[argIndex]);
result += objects[argIndex] as String;
argIndex += 1;
i = endIndex + 1;

View File

@@ -6,7 +6,7 @@
#include <Ast/astBase.hpp>
#include <Ast/functionParameters.hpp>
#include <Evaluator/Context/context.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Ast/AccessModifier.hpp>
#include <Evaluator/Value/structType.hpp>
#include <Evaluator/Value/value.hpp>
@@ -24,60 +24,60 @@ namespace Fig::Builtins
{
const TypeInfo &getErrorInterfaceTypeInfo()
{
static const TypeInfo ErrorInterfaceTypeInfo(u8"Error", true);
static const TypeInfo ErrorInterfaceTypeInfo(U"Error", true);
return ErrorInterfaceTypeInfo;
}
const TypeInfo &getTypeErrorStructTypeInfo()
{
static const TypeInfo TypeErrorStructTypeInfo(u8"TypeError", true);
static const TypeInfo TypeErrorStructTypeInfo(U"TypeError", true);
return TypeErrorStructTypeInfo;
}
const TypeInfo &getOperationInterfaceTypeInfo()
{
static const TypeInfo OperationInterfaceTypeInfo(u8"Operation", true);
static const TypeInfo OperationInterfaceTypeInfo(U"Operation", true);
return OperationInterfaceTypeInfo;
}
const std::unordered_map<FString, ObjectPtr> &getBuiltinValues()
const std::unordered_map<String, ObjectPtr> &getBuiltinValues()
{
static const std::unordered_map<FString, ObjectPtr> builtinValues = {
{u8"null", Object::getNullInstance()},
{u8"true", Object::getTrueInstance()},
{u8"false", Object::getFalseInstance()},
{u8"Error",
static const std::unordered_map<String, ObjectPtr> builtinValues = {
{U"null", Object::getNullInstance()},
{U"true", Object::getTrueInstance()},
{U"false", Object::getFalseInstance()},
{U"Error",
std::make_shared<Object>(InterfaceType(getErrorInterfaceTypeInfo(),
{Ast::InterfaceMethod(u8"toString",
{Ast::InterfaceMethod(U"toString",
Ast::FunctionParameters({}, {}),
std::make_shared<Ast::VarExprAst>(u8"String"),
std::make_shared<Ast::VarExprAst>(U"String"),
nullptr),
Ast::InterfaceMethod(u8"getErrorClass",
Ast::InterfaceMethod(U"getErrorClass",
Ast::FunctionParameters({}, {}),
std::make_shared<Ast::VarExprAst>(u8"String"),
std::make_shared<Ast::VarExprAst>(U"String"),
nullptr),
Ast::InterfaceMethod(u8"getErrorMessage",
Ast::InterfaceMethod(U"getErrorMessage",
Ast::FunctionParameters({}, {}),
std::make_shared<Ast::VarExprAst>(u8"String"),
std::make_shared<Ast::VarExprAst>(U"String"),
nullptr)}))},
{u8"TypeError", std::make_shared<Object>(StructType(
{U"TypeError", std::make_shared<Object>(StructType(
getTypeErrorStructTypeInfo(),
std::make_shared<Context>(u8"<Built-in `TypeError`>"),
{Field(AccessModifier::Public, u8"msg", ValueType::String, nullptr)}
std::make_shared<Context>(U"<Built-in `TypeError`>"),
{Field(AccessModifier::Public, U"msg", ValueType::String, nullptr)}
))},
{u8"Operation", std::make_shared<Object>(InterfaceType(getOperationInterfaceTypeInfo(), {}))},
{U"Operation", std::make_shared<Object>(InterfaceType(getOperationInterfaceTypeInfo(), {}))},
{u8"Any", std::make_shared<Object>(StructType(ValueType::Any, nullptr, {}, true))},
{u8"Int", std::make_shared<Object>(StructType(ValueType::Int, nullptr, {}, true))},
{u8"Null", std::make_shared<Object>(StructType(ValueType::Null, nullptr, {}, true))},
{u8"String", std::make_shared<Object>(StructType(ValueType::String, nullptr, {}, true))},
{u8"Bool", std::make_shared<Object>(StructType(ValueType::Bool, nullptr, {}, true))},
{u8"Double", std::make_shared<Object>(StructType(ValueType::Double, nullptr, {}, true))},
{u8"Function", std::make_shared<Object>(StructType(ValueType::Function, nullptr, {}, true))},
{u8"List", std::make_shared<Object>(StructType(ValueType::List, nullptr, {}, true))},
{u8"Map", std::make_shared<Object>(StructType(ValueType::Map, nullptr, {}, true))},
{U"Any", std::make_shared<Object>(StructType(ValueType::Any, nullptr, {}, true))},
{U"Int", std::make_shared<Object>(StructType(ValueType::Int, nullptr, {}, true))},
{U"Null", std::make_shared<Object>(StructType(ValueType::Null, nullptr, {}, true))},
{U"String", std::make_shared<Object>(StructType(ValueType::String, nullptr, {}, true))},
{U"Bool", std::make_shared<Object>(StructType(ValueType::Bool, nullptr, {}, true))},
{U"Double", std::make_shared<Object>(StructType(ValueType::Double, nullptr, {}, true))},
{U"Function", std::make_shared<Object>(StructType(ValueType::Function, nullptr, {}, true))},
{U"List", std::make_shared<Object>(StructType(ValueType::List, nullptr, {}, true))},
{U"Map", std::make_shared<Object>(StructType(ValueType::Map, nullptr, {}, true))},
// Type `StructType` `StructInstance` `Module` `InterfaceType`
// Not allowed to call constructor!
{u8"type", std::make_shared<Object>(Function(
u8"type",
{U"type", std::make_shared<Object>(Function(
U"type",
[](const std::vector<ObjectPtr> &_args) -> ObjectPtr
{
const ObjectPtr &arg = _args[0];
@@ -88,86 +88,86 @@ namespace Fig::Builtins
};
return builtinValues;
}
const std::unordered_map<FString, int> &getBuiltinFunctionArgCounts()
const std::unordered_map<String, int> &getBuiltinFunctionArgCounts()
{
static const std::unordered_map<FString, int> builtinFunctionArgCounts = {
{u8"__fstdout_print", -1}, // variadic
{u8"__fstdout_println", -1}, // variadic
{u8"__fstdin_read", 0},
{u8"__fstdin_readln", 0},
{u8"__fvalue_type", 1},
{u8"__fvalue_int_parse", 1},
{u8"__fvalue_int_from", 1},
{u8"__fvalue_double_parse", 1},
{u8"__fvalue_double_from", 1},
{u8"__fvalue_string_from", 1},
{u8"__ftime_now_ns", 0},
static const std::unordered_map<String, int> builtinFunctionArgCounts = {
{U"__fstdout_print", -1}, // variadic
{U"__fstdout_println", -1}, // variadic
{U"__fstdin_read", 0},
{U"__fstdin_readln", 0},
{U"__fvalue_type", 1},
{U"__fvalue_int_parse", 1},
{U"__fvalue_int_from", 1},
{U"__fvalue_double_parse", 1},
{U"__fvalue_double_from", 1},
{U"__fvalue_string_from", 1},
{U"__ftime_now_ns", 0},
/* math start */
{u8"__fmath_acos", 1},
{u8"__fmath_acosh", 1},
{u8"__fmath_asin", 1},
{u8"__fmath_asinh", 1},
{u8"__fmath_atan", 1},
{u8"__fmath_atan2", 2},
{u8"__fmath_atanh", 1},
{u8"__fmath_ceil", 1},
{u8"__fmath_cos", 1},
{u8"__fmath_cosh", 1},
{u8"__fmath_exp", 1},
{u8"__fmath_expm1", 1},
{u8"__fmath_fabs", 1},
{u8"__fmath_floor", 1},
{u8"__fmath_fmod", 2},
{u8"__fmath_frexp", 1},
{u8"__fmath_gcd", 2},
{u8"__fmath_hypot", 2},
{u8"__fmath_isequal", 2},
{u8"__fmath_log", 1},
{u8"__fmath_log10", 1},
{u8"__fmath_log1p", 1},
{u8"__fmath_log2", 1},
{u8"__fmath_sin", 1},
{u8"__fmath_sinh", 1},
{u8"__fmath_sqrt", 1},
{u8"__fmath_tan", 1},
{u8"__fmath_tanh", 1},
{u8"__fmath_trunc", 1},
{U"__fmath_acos", 1},
{U"__fmath_acosh", 1},
{U"__fmath_asin", 1},
{U"__fmath_asinh", 1},
{U"__fmath_atan", 1},
{U"__fmath_atan2", 2},
{U"__fmath_atanh", 1},
{U"__fmath_ceil", 1},
{U"__fmath_cos", 1},
{U"__fmath_cosh", 1},
{U"__fmath_exp", 1},
{U"__fmath_expm1", 1},
{U"__fmath_fabs", 1},
{U"__fmath_floor", 1},
{U"__fmath_fmod", 2},
{U"__fmath_frexp", 1},
{U"__fmath_gcd", 2},
{U"__fmath_hypot", 2},
{U"__fmath_isequal", 2},
{U"__fmath_log", 1},
{U"__fmath_log10", 1},
{U"__fmath_log1p", 1},
{U"__fmath_log2", 1},
{U"__fmath_sin", 1},
{U"__fmath_sinh", 1},
{U"__fmath_sqrt", 1},
{U"__fmath_tan", 1},
{U"__fmath_tanh", 1},
{U"__fmath_trunc", 1},
};
return builtinFunctionArgCounts;
}
const std::unordered_map<FString, BuiltinFunction> &getBuiltinFunctions()
const std::unordered_map<String, BuiltinFunction> &getBuiltinFunctions()
{
static const std::unordered_map<FString, BuiltinFunction> builtinFunctions{
{u8"__fstdout_print",
static const std::unordered_map<String, BuiltinFunction> builtinFunctions{
{U"__fstdout_print",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
return std::make_shared<Object>(ValueType::IntClass(args.size()));
}},
{u8"__fstdout_println",
{U"__fstdout_println",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
std::print("\n");
return std::make_shared<Object>(ValueType::IntClass(args.size()));
}},
{u8"__fstdin_read",
{U"__fstdin_read",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
std::string input;
std::cin >> input;
return std::make_shared<Object>(FString::fromBasicString(input));
return std::make_shared<Object>(String(input));
}},
{u8"__fstdin_readln",
{U"__fstdin_readln",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
std::string line;
std::getline(std::cin, line);
return std::make_shared<Object>(FString::fromBasicString(line));
return std::make_shared<Object>(String(line));
}},
{u8"__fvalue_type",
{U"__fvalue_type",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
return std::make_shared<Object>(args[0]->getTypeInfo().toString());
}},
{u8"__fvalue_int_parse",
{U"__fvalue_int_parse",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
FString str = args[0]->as<ValueType::StringClass>();
String str = args[0]->as<ValueType::StringClass>();
try
{
ValueType::IntClass val = std::stoi(str.toBasicString());
@@ -175,10 +175,10 @@ namespace Fig::Builtins
}
catch (...)
{
throw RuntimeError(FString(std::format("Invalid int string for parsing", str.toBasicString())));
throw RuntimeError(String(std::format("Invalid int string for parsing", str.toBasicString())));
}
}},
{u8"__fvalue_int_from",
{U"__fvalue_int_from",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
if (val->is<ValueType::DoubleClass>())
@@ -193,13 +193,13 @@ namespace Fig::Builtins
}
else
{
throw RuntimeError(FString(std::format("Type '{}' cannot be converted to int",
throw RuntimeError(String(std::format("Type '{}' cannot be converted to int",
val->getTypeInfo().toString().toBasicString())));
}
}},
{u8"__fvalue_double_parse",
{U"__fvalue_double_parse",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
FString str = args[0]->as<ValueType::StringClass>();
String str = args[0]->as<ValueType::StringClass>();
try
{
ValueType::DoubleClass val = std::stod(str.toBasicString());
@@ -207,10 +207,10 @@ namespace Fig::Builtins
}
catch (...)
{
throw RuntimeError(FString(std::format("Invalid double string for parsing", str.toBasicString())));
throw RuntimeError(String(std::format("Invalid double string for parsing", str.toBasicString())));
}
}},
{u8"__fvalue_double_from",
{U"__fvalue_double_from",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
if (val->is<ValueType::IntClass>())
@@ -225,16 +225,16 @@ namespace Fig::Builtins
}
else
{
throw RuntimeError(FString(std::format("Type '{}' cannot be converted to double",
throw RuntimeError(String(std::format("Type '{}' cannot be converted to double",
val->getTypeInfo().toString().toBasicString())));
}
}},
{u8"__fvalue_string_from",
{U"__fvalue_string_from",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
return std::make_shared<Object>(val->toStringIO());
}},
{u8"__ftime_now_ns",
{U"__ftime_now_ns",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
// returns nanoseconds
using namespace Fig::Time;
@@ -244,97 +244,97 @@ namespace Fig::Builtins
}},
/* math start */
{u8"__fmath_acos",
{U"__fmath_acos",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(acos(d));
}},
{u8"__fmath_acosh",
{U"__fmath_acosh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(acosh(d));
}},
{u8"__fmath_asin",
{U"__fmath_asin",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(asin(d));
}},
{u8"__fmath_asinh",
{U"__fmath_asinh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(asinh(d));
}},
{u8"__fmath_atan",
{U"__fmath_atan",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(atan(d));
}},
{u8"__fmath_atan2",
{U"__fmath_atan2",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass y = args[0]->getNumericValue();
ValueType::DoubleClass x = args[1]->getNumericValue();
return std::make_shared<Object>(atan2(y, x));
}},
{u8"__fmath_atanh",
{U"__fmath_atanh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(atanh(d));
}},
{u8"__fmath_ceil",
{U"__fmath_ceil",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(ceil(d));
}},
{u8"__fmath_cos",
{U"__fmath_cos",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(cos(d));
}},
{u8"__fmath_cosh",
{U"__fmath_cosh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(cosh(d));
}},
{u8"__fmath_exp",
{U"__fmath_exp",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(exp(d));
}},
{u8"__fmath_expm1",
{U"__fmath_expm1",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(expm1(d));
}},
{u8"__fmath_fabs",
{U"__fmath_fabs",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(fabs(d));
}},
{u8"__fmath_floor",
{U"__fmath_floor",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(floor(d));
}},
{u8"__fmath_fmod",
{U"__fmath_fmod",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue();
return std::make_shared<Object>(fmod(x, y));
}},
{u8"__fmath_frexp",
{U"__fmath_frexp",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
@@ -342,80 +342,80 @@ namespace Fig::Builtins
return std::make_shared<Object>(List({std::make_shared<Object>(frexp(d, &e)),
std::make_shared<Object>(static_cast<ValueType::IntClass>(e))}));
}},
{u8"__fmath_gcd",
{U"__fmath_gcd",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::IntClass x = args[0]->as<ValueType::IntClass>();
ValueType::IntClass y = args[1]->as<ValueType::IntClass>();
return std::make_shared<Object>(std::gcd(x, y));
}},
{u8"__fmath_hypot",
{U"__fmath_hypot",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue();
return std::make_shared<Object>(hypot(x, y));
}},
{u8"__fmath_isequal",
{U"__fmath_isequal",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue();
static const double epsilon = 1e-9;
return std::make_shared<Object>(fabs(x - y) < epsilon);
}},
{u8"__fmath_log",
{U"__fmath_log",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log(d));
}},
{u8"__fmath_log10",
{U"__fmath_log10",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log10(d));
}},
{u8"__fmath_log1p",
{U"__fmath_log1p",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log1p(d));
}},
{u8"__fmath_log2",
{U"__fmath_log2",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log2(d));
}},
{u8"__fmath_sin",
{U"__fmath_sin",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sin(d));
}},
{u8"__fmath_sinh",
{U"__fmath_sinh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sinh(d));
}},
{u8"__fmath_sqrt",
{U"__fmath_sqrt",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sqrt(d));
}},
{u8"__fmath_tan",
{U"__fmath_tan",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(tan(d));
}},
{u8"__fmath_tanh",
{U"__fmath_tanh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(tanh(d));
}},
{u8"__fmath_trunc",
{U"__fmath_trunc",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue();

View File

@@ -3,7 +3,7 @@
#include <Ast/Expressions/VarExpr.hpp>
#include <Ast/functionParameters.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/value.hpp>
#include <Core/runtimeTime.hpp>
@@ -39,34 +39,34 @@ namespace Fig
const TypeInfo &getOperationInterfaceTypeInfo();
const std::unordered_map<FString, ObjectPtr> &getBuiltinValues();
const std::unordered_map<String, ObjectPtr> &getBuiltinValues();
using BuiltinFunction = std::function<ObjectPtr(const std::vector<ObjectPtr> &)>;
const std::unordered_map<FString, int> &getBuiltinFunctionArgCounts();
const std::unordered_map<FString, BuiltinFunction> &getBuiltinFunctions();
const std::unordered_map<String, int> &getBuiltinFunctionArgCounts();
const std::unordered_map<String, BuiltinFunction> &getBuiltinFunctions();
inline bool isBuiltinFunction(const FString &name)
inline bool isBuiltinFunction(const String &name)
{
return getBuiltinFunctions().find(name) != getBuiltinFunctions().end();
}
inline BuiltinFunction getBuiltinFunction(const FString &name)
inline BuiltinFunction getBuiltinFunction(const String &name)
{
auto it = getBuiltinFunctions().find(name);
if (it == getBuiltinFunctions().end())
{
throw RuntimeError(FString(std::format("Builtin function '{}' not found", name.toBasicString())));
throw RuntimeError(String(std::format("Builtin function '{}' not found", name.toBasicString())));
}
return it->second;
}
inline int getBuiltinFunctionParamCount(const FString &name)
inline int getBuiltinFunctionParamCount(const String &name)
{
auto it = getBuiltinFunctionArgCounts().find(name);
if (it == getBuiltinFunctionArgCounts().end())
{
throw RuntimeError(FString(std::format("Builtin function '{}' not found", name.toBasicString())));
throw RuntimeError(String(std::format("Builtin function '{}' not found", name.toBasicString())));
}
return it->second;
}

View File

@@ -1,3 +1,4 @@
#include "Ast/Expressions/InitExpr.hpp"
#include <Ast/Expressions/VarExpr.hpp>
#include <Ast/Statements/ErrorFlow.hpp>
#include <Ast/Statements/ImplementSt.hpp>
@@ -6,6 +7,7 @@
#include <Error/error.hpp>
#include <Token/token.hpp>
#include <Parser/parser.hpp>
#include <memory>
namespace Fig
{
@@ -85,7 +87,7 @@ namespace Fig
bool isConst = (currentToken().getType() == TokenType::Const ? true : false);
next();
expect(TokenType::Identifier);
FString name = currentToken().getValue();
String name = currentToken().getValue();
next();
Ast::Expression declaredType = nullptr;
bool hasSpecificType = false;
@@ -100,12 +102,12 @@ namespace Fig
next(); // consume `;`, no using expectConsume here cause we don't need to check again
return makeAst<Ast::VarDefAst>(isPublic, isConst, name, declaredType, nullptr, false);
}
if (!isThis(TokenType::Assign) and !isThis(TokenType::Walrus)) expect(TokenType::Assign, u8"assign or walrus");
if (!isThis(TokenType::Assign) and !isThis(TokenType::Walrus)) expect(TokenType::Assign, U"\1");
bool followupType = false;
if (isThis(TokenType::Walrus))
{
if (hasSpecificType) throwAddressableError<SyntaxError>(FString(u8""));
if (hasSpecificType) throwAddressableError<SyntaxError>(String(U"\1"));
followupType = true;
}
next();
@@ -116,7 +118,7 @@ namespace Fig
ObjectPtr Parser::__parseValue()
{
FString _val = currentToken().getValue();
String _val = currentToken().getValue();
if (currentToken().getType() == TokenType::LiteralNumber)
{
if (_val.contains(u8'.') || _val.contains(u8'e'))
@@ -129,7 +131,7 @@ namespace Fig
}
catch (...)
{
throwAddressableError<SyntaxError>(FString(u8"Illegal number literal"));
throwAddressableError<SyntaxError>(String(U"\1"));
}
return std::make_shared<Object>(d);
}
@@ -143,7 +145,7 @@ namespace Fig
}
catch (...)
{
throwAddressableError<SyntaxError>(FString(u8"Illegal number literal"));
throwAddressableError<SyntaxError>(String(U"\1"));
}
return std::make_shared<Object>(i);
}
@@ -151,7 +153,7 @@ namespace Fig
else if (currentToken().getType() == TokenType::LiteralString) { return std::make_shared<Object>(_val); }
else if (currentToken().getType() == TokenType::LiteralBool)
{
return std::make_shared<Object>((_val == u8"true" ? true : false));
return std::make_shared<Object>((_val == U"\1" ? true : false));
}
else if (currentToken().getType() == TokenType::LiteralNull) { return Object::getNullInstance(); }
else
@@ -174,7 +176,7 @@ namespace Fig
Ast::FunctionParameters::PosParasType pp;
Ast::FunctionParameters::DefParasType dp;
FString variaPara;
String variaPara;
while (true)
{
if (isThis(TokenType::RightParen))
@@ -182,13 +184,13 @@ namespace Fig
next();
return Ast::FunctionParameters(pp, dp);
}
expect(TokenType::Identifier, FString(u8"Identifier or `)`")); // check current
FString pname = currentToken().getValue();
expect(TokenType::Identifier, String(U"\1")); // check current
String pname = currentToken().getValue();
next(); // skip pname
if (isThis(TokenType::Assign)) // =
{
next();
dp.push_back({pname, {makeAst<Ast::VarExprAst>(u8"Any"), parseExpression(0, TokenType::Comma)}});
dp.push_back({pname, {makeAst<Ast::VarExprAst>(U"\1"), parseExpression(0, TokenType::Comma)}});
if (isThis(TokenType::Comma))
{
next(); // only skip `,` when it's there
@@ -222,16 +224,13 @@ namespace Fig
variaPara = pname;
next(); // skip `...`
if (!isThis(TokenType::RightParen))
throwAddressableError<SyntaxError>(
u8"Expects right paren, variable parameter function can only have one parameter",
currentAAI.line,
currentAAI.column);
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
next(); // skip `)`
return Ast::FunctionParameters(variaPara);
}
else
{
pp.push_back({pname, makeAst<Ast::VarExprAst>(u8"Any")});
pp.push_back({pname, makeAst<Ast::VarExprAst>(U"\1")});
if (isThis(TokenType::Comma))
{
next(); // only skip `,` when it's there
@@ -241,7 +240,7 @@ namespace Fig
}
Ast::FunctionDef Parser::__parseFunctionDef(bool isPublic)
{
FString funcName = currentToken().getValue();
String funcName = currentToken().getValue();
next();
expect(TokenType::LeftParen);
Ast::FunctionParameters params = __parseFunctionParameters();
@@ -260,9 +259,9 @@ namespace Fig
Ast::StructDef Parser::__parseStructDef(bool isPublic)
{
// entry: current is struct name
FString structName = currentToken().getValue();
String structName = currentToken().getValue();
next();
expect(TokenType::LeftBrace, u8"struct body");
expect(TokenType::LeftBrace, U"\1");
next();
bool braceClosed = false;
@@ -279,7 +278,7 @@ namespace Fig
auto __parseStructField = [this](bool isPublic) -> Ast::StructDefField {
AccessModifier am = AccessModifier::Normal;
FString fieldName;
String fieldName;
if (isThis(TokenType::Identifier))
{
fieldName = currentToken().getValue();
@@ -289,13 +288,13 @@ namespace Fig
else if (isThis(TokenType::Const))
{
next();
expect(TokenType::Identifier, u8"field name");
expect(TokenType::Identifier, U"\1");
fieldName = currentToken().getValue();
am = (isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
}
else
{
throwAddressableError<SyntaxError>(FString(std::format("expect field name or field attribute")));
throwAddressableError<SyntaxError>(String(std::format("expect field name or field attribute")));
}
Ast::Expression fieldType = nullptr;
if (isThis(TokenType::Colon))
@@ -307,7 +306,7 @@ namespace Fig
if (isThis(TokenType::Assign))
{
next();
if (isEOF()) throwAddressableError<SyntaxError>(FString(u8"expect an expression"));
if (isEOF()) throwAddressableError<SyntaxError>(String(U"\1"));
initExpr = parseExpression(0);
}
expectSemicolon();
@@ -351,7 +350,7 @@ namespace Fig
}
else
{
throwAddressableError<SyntaxError>(FString("Invalid syntax"));
throwAddressableError<SyntaxError>(String("Invalid syntax"));
}
}
else if (isThis(TokenType::Function))
@@ -368,21 +367,21 @@ namespace Fig
else if (isThis(TokenType::Variable))
{
throwAddressableError<SyntaxError>(
FString("Variables are not allowed to be defined within a structure."));
String("Variables are not allowed to be defined within a structure."));
}
else
{
throwAddressableError<SyntaxError>(FString("Invalid syntax"));
throwAddressableError<SyntaxError>(String("Invalid syntax"));
}
}
if (!braceClosed) { throwAddressableError<SyntaxError>(FString("braces are not closed")); }
if (!braceClosed) { throwAddressableError<SyntaxError>(String("braces are not closed")); }
return makeAst<Ast::StructDefSt>(isPublic, structName, fields, makeAst<Ast::BlockStatementAst>(stmts));
}
Ast::InterfaceDef Parser::__parseInterfaceDef(bool isPublic)
{
// entry: current is interface name
FString interfaceName = currentToken().getValue();
String interfaceName = currentToken().getValue();
next(); // consume name
expect(TokenType::LeftBrace); // `{
next(); // consume `{`
@@ -398,7 +397,7 @@ namespace Fig
}
if (isThis(TokenType::Identifier))
{
FString funcName = currentToken().getValue();
String funcName = currentToken().getValue();
next(); // consume func name
expect(TokenType::LeftParen);
@@ -422,7 +421,7 @@ namespace Fig
}
else
{
throwAddressableError<SyntaxError>(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column);
throwAddressableError<SyntaxError>(String(U"\1"), currentAAI.line, currentAAI.column);
}
}
return makeAst<Ast::InterfaceDefAst>(interfaceName, methods, isPublic);
@@ -432,15 +431,15 @@ namespace Fig
{
// entry: current is `impl`
next(); // consume `impl`
expect(TokenType::Identifier, u8"interface name");
FString interfaceName = currentToken().getValue();
expect(TokenType::Identifier, U"\1");
String interfaceName = currentToken().getValue();
next(); // consume interface name
expect(TokenType::For);
next(); // consume `for`
expect(TokenType::Identifier, u8"struct name");
FString structName = currentToken().getValue();
expect(TokenType::Identifier, U"\1");
String structName = currentToken().getValue();
next(); // consume name
expect(TokenType::LeftBrace); // {
next(); // consume `{`
@@ -456,7 +455,7 @@ namespace Fig
}
if (isThis(TokenType::Identifier))
{
FString funcName = currentToken().getValue();
String funcName = currentToken().getValue();
next(); // consume func name
expect(TokenType::LeftParen);
Ast::FunctionParameters paras = __parseFunctionParameters();
@@ -466,7 +465,7 @@ namespace Fig
}
else
{
throwAddressableError<SyntaxError>(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column);
throwAddressableError<SyntaxError>(String(U"\1"), currentAAI.line, currentAAI.column);
}
}
@@ -511,16 +510,16 @@ namespace Fig
next(); // consume `catch`
expect(TokenType::LeftParen);
next(); // consume `(`
expect(TokenType::Identifier, u8"error receive var name");
FString errVarName = currentToken().getValue();
expect(TokenType::Identifier, U"\1");
String errVarName = currentToken().getValue();
next(); // consume name
bool hasType = false;
FString errVarType;
String errVarType;
if (isThis(TokenType::Colon)) // :
{
next();
expect(TokenType::Identifier, u8"error type");
expect(TokenType::Identifier, U"\1");
errVarType = currentToken().getValue();
next(); // consume var type
hasType = true;
@@ -540,8 +539,7 @@ namespace Fig
{
if (finallyBlock != nullptr)
{
throwAddressableError<SyntaxError>(
u8"Duplicate try finally-block", currentAAI.line, currentAAI.column);
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
}
next(); // consume `finally`
expect(TokenType::LeftBrace);
@@ -577,8 +575,7 @@ namespace Fig
else if (isThis(TokenType::Interface)) { stmt = __parseInterfaceDef(true); }
else
{
throwAddressableError<SyntaxError>(
FString(u8"Expected `var`, `const`, `function`, `struct` or `interface` after `public`"));
throwAddressableError<SyntaxError>(String(U"\1"));
}
}
else if (isThis(TokenType::Variable) || isThis(TokenType::Const)) { stmt = __parseVarDef(false); }
@@ -589,22 +586,19 @@ namespace Fig
}
else if (isThis(TokenType::Struct))
{
expectPeek(TokenType::Identifier, u8"struct name");
expectPeek(TokenType::Identifier, U"\1");
next();
stmt = __parseStructDef(false);
}
else if (isThis(TokenType::Interface))
{
expectPeek(TokenType::Identifier, u8"interface name");
expectPeek(TokenType::Identifier, U"\1");
next();
stmt = __parseInterfaceDef(false);
}
else if (isThis(TokenType::Implement)) { stmt = __parseImplement(); }
else if (isThis(TokenType::If)) { stmt = __parseIf(); }
else if (isThis(TokenType::Else))
{
throwAddressableError<SyntaxError>(FString(u8"`else` without matching `if`"));
}
else if (isThis(TokenType::Else)) { throwAddressableError<SyntaxError>(String(U"\1")); }
else if (isThis(TokenType::LeftBrace)) { stmt = __parseBlockStatement(); }
else if (isThis(TokenType::While)) { stmt = __parseWhile(); }
else if (isThis(TokenType::For)) { stmt = __parseFor(); }
@@ -622,7 +616,7 @@ namespace Fig
}
else
{
throwAddressableError<SyntaxError>(u8"invalid syntax", currentAAI.line, currentAAI.column);
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
}
return stmt;
}
@@ -722,15 +716,12 @@ namespace Fig
// 2. expression stmti++, foo()
// ❌ not allowedif/while/for/block stmt
if (isThis(TokenType::LeftBrace))
{
throwAddressableError<SyntaxError>(u8"BlockStatement cannot be used as for loop increment");
}
if (isThis(TokenType::LeftBrace)) { throwAddressableError<SyntaxError>(U"\1"); }
if (isThis(TokenType::If) || isThis(TokenType::While) || isThis(TokenType::For) || isThis(TokenType::Return)
|| isThis(TokenType::Break) || isThis(TokenType::Continue))
{
throwAddressableError<SyntaxError>(u8"Control flow statements cannot be used as for loop increment");
throwAddressableError<SyntaxError>(U"\1");
}
Ast::Expression exp = parseExpression(0, TokenType::LeftBrace);
@@ -784,7 +775,7 @@ namespace Fig
return makeAst<Ast::BreakSt>();
}
Ast::VarExpr Parser::__parseVarExpr(FString name)
Ast::VarExpr Parser::__parseVarExpr(String name)
{
return makeAst<Ast::VarExprAst>(name);
}
@@ -867,7 +858,7 @@ namespace Fig
{
// entry: current is `{`
next(); // consume `{`
std::vector<std::pair<FString, Ast::Expression>> args;
std::vector<std::pair<String, Ast::Expression>> args;
/*
3 ways of calling constructor
.1 Person {"Fig", 1, "IDK"};
@@ -881,10 +872,6 @@ namespace Fig
if (mode == 0)
{
if (isThis(TokenType::Identifier) && isNext(TokenType::Colon)) { mode = 2; }
else if (isThis(TokenType::Identifier) && (isNext(TokenType::Comma) || isNext(TokenType::RightBrace)))
{
mode = 3;
}
else
{
mode = 1;
@@ -895,29 +882,19 @@ namespace Fig
{
// 1 Person {"Fig", 1, "IDK"};
Ast::Expression expr = parseExpression(0, TokenType::Comma, TokenType::RightBrace);
args.push_back({FString(), std::move(expr)});
args.push_back({String(), std::move(expr)});
}
else if (mode == 2)
{
// 2 Person {name: "Fig", age: 1, sex: "IDK"};
expect(TokenType::Identifier);
FString fieldName = currentToken().getValue();
String fieldName = currentToken().getValue();
next(); // consume identifier
expect(TokenType::Colon);
next(); // consume colon
Ast::Expression expr = parseExpression(0, TokenType::Comma, TokenType::RightBrace);
args.push_back({fieldName, std::move(expr)});
}
else if (mode == 3)
{
// 3 Person {name, age, sex};
expect(TokenType::Identifier);
FString fieldName = currentToken().getValue();
Ast::Expression expr = makeAst<Ast::VarExprAst>(fieldName);
args.push_back({fieldName, std::move(expr)});
next(); // consume identifier
}
if (isThis(TokenType::Comma))
{
next(); // consume comma
@@ -925,10 +902,31 @@ namespace Fig
else if (!isThis(TokenType::RightBrace))
{
throwAddressableError<SyntaxError>(
FString(std::format("Expect `,` or `}}` in struct initialization expression, got {}",
currentToken().toString().toBasicString())));
String(std::format("Expect `,` or `}}` in struct initialization expression, got {}",
currentToken().toString().toBasicString())));
}
}
bool shorthand = true;
if (mode == 1)
{
for (auto &[name, exp] : args)
{
if (!name.empty()) { shorthand = false; }
if (exp->getType() != Ast::AstType::VarExpr) { shorthand = false; }
}
if (shorthand)
{
mode = 3; // all are identifiers, so it's shorthand mode, not positional
std::vector<std::pair<String, Ast::Expression>> nargs;
for (auto &[name, exp] : args)
{
const Ast::VarExpr var = std::static_pointer_cast<Ast::VarExprAst>(exp);
nargs.push_back({var->name, exp});
}
args = nargs;
}
}
expect(TokenType::RightBrace);
next(); // consume `}`
return makeAst<Ast::InitExprAst>(structe, args, static_cast<Ast::InitExprAst::InitMode>(mode));
@@ -972,7 +970,7 @@ namespace Fig
}
else
{
throwAddressableError<SyntaxError>(FString(u8"Expect ')' or ',' after expression in parentheses"));
throwAddressableError<SyntaxError>(String(U"\1"));
}
return nullptr; // to suppress compiler warning
}
@@ -1000,12 +998,12 @@ namespace Fig
Ast::Import Parser::__parseImport()
{
next(); // consume `import`
std::vector<FString> path;
std::vector<FString> names;
FString rename;
std::vector<String> path;
std::vector<String> names;
String rename;
while (true)
{
expect(TokenType::Identifier, u8"package name");
expect(TokenType::Identifier, U"\1");
path.push_back(currentToken().getValue());
next(); // consume package name
if (isThis(TokenType::Semicolon)) { break; }
@@ -1017,13 +1015,13 @@ namespace Fig
else if (isThis(TokenType::LeftBrace)) { break; }
else
{
throwAddressableError<SyntaxError>(u8"invalid syntax");
throwAddressableError<SyntaxError>(U"\1");
}
}
if (isThis(TokenType::As))
{
next(); // consume `as`
expect(TokenType::Identifier, u8"new name");
expect(TokenType::Identifier, U"\1");
rename = currentToken().getValue();
next(); // consume name
}
@@ -1041,7 +1039,7 @@ namespace Fig
{
next(); // consume `,`
}
expect(TokenType::Identifier, u8"symbol name");
expect(TokenType::Identifier, U"\1");
names.push_back(currentToken().getValue());
next();
}
@@ -1056,10 +1054,10 @@ namespace Fig
Ast::Operator op;
Token tok = currentToken();
if (tok == EOFTok) throwAddressableError<SyntaxError>(FString(u8"Unexpected end of expression"));
if (tok == EOFTok) throwAddressableError<SyntaxError>(String(U"\1"));
if (tok.getType() == stop || tok.getType() == stop2 || tok.getType() == stop3)
{
if (lhs == nullptr) throwAddressableError<SyntaxError>(FString(u8"Expected expression"));
if (lhs == nullptr) throwAddressableError<SyntaxError>(String(U"\1"));
return lhs;
}
if (tok.getType() == TokenType::LeftBracket)
@@ -1080,7 +1078,7 @@ namespace Fig
if (currentToken().getType() == TokenType::Identifier)
{
// err
throwAddressableError<SyntaxError>(FString(u8"Function literal should not have a name"));
throwAddressableError<SyntaxError>(String(U"\1"));
}
expect(TokenType::LeftParen);
lhs = __parseFunctionLiteralExpr();
@@ -1092,7 +1090,7 @@ namespace Fig
}
else if (tok.isIdentifier())
{
FString id = tok.getValue();
String id = tok.getValue();
next();
lhs = __parseVarExpr(id);
}
@@ -1112,7 +1110,7 @@ namespace Fig
}
else
{
throwAddressableError<SyntaxError>(FString(u8"Unexpected token in expression:") + tok.toString());
throwAddressableError<SyntaxError>(String(U"\1") + tok.toString());
}
// infix / (postfix) ?
@@ -1123,11 +1121,7 @@ namespace Fig
/* Postfix */
if (tok.getType() == TokenType::LeftBrace)
{
throwAddressableError<SyntaxError>(
FString(u8"Since Fig v0.4.2, please use new struct{} to avoid syntax ambiguity"));
}
if (tok.getType() == TokenType::LeftBrace) { throwAddressableError<SyntaxError>(String(U"\1")); }
if (tok.getType() == TokenType::LeftParen)
{
@@ -1150,10 +1144,9 @@ namespace Fig
{
next(); // consume '.'
Token idTok = currentToken();
if (!idTok.isIdentifier())
throwAddressableError<SyntaxError>(FString(u8"Expected identifier after '.'"));
if (!idTok.isIdentifier()) throwAddressableError<SyntaxError>(String(U"\1"));
FString member = idTok.getValue();
String member = idTok.getValue();
next(); // consume identifier
lhs = makeAst<Ast::MemberExprAst>(lhs, member);
@@ -1209,8 +1202,7 @@ namespace Fig
auto stmt = __parseStatement();
if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt)
{
throwAddressableError<SyntaxError>(
u8"Package must be at the beginning of the file", currentAAI.line, currentAAI.column);
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
}
pushNode(stmt);
}

View File

@@ -4,7 +4,7 @@
#include <Ast/astBase.hpp>
#include <Ast/ast.hpp>
#include <Lexer/lexer.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Error/error.hpp>
#include <memory>
@@ -23,8 +23,8 @@ namespace Fig
std::vector<Ast::AstBase> output;
std::vector<Token> previousTokens;
std::shared_ptr<FString> sourcePathPtr;
std::shared_ptr<std::vector<FString>> sourceLinesPtr;
std::shared_ptr<String> sourcePathPtr;
std::shared_ptr<std::vector<String>> sourceLinesPtr;
size_t tokenPruduced = 0;
size_t currentTokenIndex = 0;
@@ -76,16 +76,16 @@ namespace Fig
static const std::unordered_map<Ast::Operator, std::pair<Precedence, Precedence>> opPrecedence;
static const std::unordered_map<Ast::Operator, Precedence> unaryOpPrecedence;
Parser(const Lexer &_lexer, FString _sourcePath, std::vector<FString> _sourceLines) : lexer(_lexer)
Parser(const Lexer &_lexer, String _sourcePath, std::vector<String> _sourceLines) : lexer(_lexer)
{
sourcePathPtr = std::make_shared<FString>(_sourcePath);
sourceLinesPtr = std::make_shared<std::vector<FString>>(_sourceLines);
sourcePathPtr = std::make_shared<String>(_sourcePath);
sourceLinesPtr = std::make_shared<std::vector<String>>(_sourceLines);
}
AddressableError *getError() const { return error.get(); }
template <class _ErrT, typename = AddressableError>
void throwAddressableError(FString msg,
void throwAddressableError(String msg,
size_t line,
size_t column,
std::source_location loc = std::source_location::current())
@@ -96,7 +96,7 @@ namespace Fig
throw spError;
}
template <class _ErrT, typename = AddressableError>
void throwAddressableError(FString msg, std::source_location loc = std::source_location::current())
void throwAddressableError(String msg, std::source_location loc = std::source_location::current())
{
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
// line, column provide by `currentAAI`
@@ -106,7 +106,7 @@ namespace Fig
}
template <class _ErrT, typename = UnaddressableError>
void throwUnaddressableError(FString msg, std::source_location loc = std::source_location::current())
void throwUnaddressableError(String msg, std::source_location loc = std::source_location::current())
{
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
_ErrT spError(msg, loc);
@@ -202,9 +202,9 @@ namespace Fig
{
if (peekToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(peekToken().getType()))),
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(peekToken().getType()))),
loc);
}
}
@@ -213,34 +213,32 @@ namespace Fig
{
if (currentToken().getType() != type)
{
throwAddressableError<SyntaxError>(
FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(currentToken().getType()))),
loc);
}
}
void expectPeek(TokenType type, FString expected, std::source_location loc = std::source_location::current())
{
if (peekToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(peekToken().getType()))),
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(currentToken().getType()))),
loc);
}
}
void expect(TokenType type, FString expected, std::source_location loc = std::source_location::current())
void expectPeek(TokenType type, String expected, std::source_location loc = std::source_location::current())
{
if (peekToken().getType() != type)
{
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(peekToken().getType()))),
loc);
}
}
void expect(TokenType type, String expected, std::source_location loc = std::source_location::current())
{
if (currentToken().getType() != type)
{
throwAddressableError<SyntaxError>(
FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(currentToken().getType()))),
loc);
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(currentToken().getType()))),
loc);
}
}
@@ -264,7 +262,7 @@ namespace Fig
expectConsume(TokenType::Semicolon, loc);
}
void expectConsume(TokenType type, FString expected, std::source_location loc = std::source_location::current())
void expectConsume(TokenType type, String expected, std::source_location loc = std::source_location::current())
{
expect(type, expected, loc);
next();
@@ -279,8 +277,6 @@ namespace Fig
bool isNext(TokenType type) { return peekToken().getType() == type; }
bool isThis(TokenType type) { return currentToken().getType() == type; }
static constexpr FString varDefTypeFollowed = u8"(Followed)";
Ast::VarDef __parseVarDef(bool); // entry: current is keyword `var` or `const` (isConst: Bool)
ObjectPtr __parseValue();
Ast::ValueExpr __parseValueExpr();
@@ -294,7 +290,7 @@ namespace Fig
Ast::Break __parseBreak(); // entry: current is Token::Break
Ast::Continue __parseContinue(); // entry: current is Token::Continue
Ast::VarExpr __parseVarExpr(FString);
Ast::VarExpr __parseVarExpr(String);
Ast::FunctionDef __parseFunctionDef(bool); // entry: current is Token::Identifier (isPublic: Bool)
Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool)
Ast::InterfaceDef

View File

@@ -1,7 +1,7 @@
#include <Ast/astBase.hpp>
#include <Error/error.hpp>
#include <Error/errorLog.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Repl/Repl.hpp>
#include <vector>
@@ -11,8 +11,8 @@ namespace Fig
{
ostream << getPrompt() << "\n";
const FString &sourcePath = u8"<stdin>";
const std::vector<FString> &sourceLines{};
const String &sourcePath = U"<stdin>";
const std::vector<String> &sourceLines{};
Evaluator evaluator;
@@ -24,7 +24,7 @@ namespace Fig
while (true)
{
ostream << "\r\n>>";
const FString &line = readline();
const String &line = readline();
if (line.empty())
{

View File

@@ -28,12 +28,12 @@ namespace Fig
{
}
FString readline() const
String readline() const
{
std::string buf;
std::getline(istream, buf);
return FString(buf);
return String(buf);
}
static std::string getPrompt()

View File

@@ -4,7 +4,7 @@
#include <format>
#include <Utils/magic_enum/magic_enum.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
namespace Fig
{
@@ -54,7 +54,7 @@ namespace Fig
/* Literal Types (not keyword)*/
LiteralNumber, // number (int,float...)
LiteralString, // FString
LiteralString, // String
LiteralBool, // bool (true/false)
LiteralNull, // null (Null unique instance)
@@ -121,56 +121,40 @@ namespace Fig
friend bool operator==(const Token &l, const Token &r);
private:
FString value;
String value;
TokenType type;
public:
size_t line, column;
inline Token() {};
inline Token(const FString &_value, TokenType _type) :
value(_value), type(_type) {}
inline Token(const FString &_value, TokenType _type, size_t _line, size_t _column) :
value(_value), type(_type)
inline Token(const String &_value, TokenType _type) : value(_value), type(_type) {}
inline Token(const String &_value, TokenType _type, size_t _line, size_t _column) : value(_value), type(_type)
{
line = _line;
column = _column;
}
const Token& setPos(size_t _line, size_t _column)
const Token &setPos(size_t _line, size_t _column)
{
line = _line;
column = _column;
return *this;
}
size_t getLength()
size_t getLength() { return value.length(); }
const String &getValue() const { return value; }
inline String toString() const
{
return value.length();
}
const FString& getValue() const
{
return value;
}
inline FString toString() const
{
return FString(std::format(
"Token('{}',{})",
this->value.toBasicString(),
magic_enum::enum_name(type)));
return String(std::format("Token('{}',{})", this->value.toBasicString(), magic_enum::enum_name(type)));
}
bool isIdentifier()
{
return type == TokenType::Identifier;
}
bool isIdentifier() { return type == TokenType::Identifier; }
bool isLiteral()
{
return type == TokenType::LiteralNull || type == TokenType::LiteralBool || type == TokenType::LiteralNumber || type == TokenType::LiteralString;
return type == TokenType::LiteralNull || type == TokenType::LiteralBool || type == TokenType::LiteralNumber
|| type == TokenType::LiteralString;
}
TokenType getType() const
{
return type;
}
TokenType getType() const { return type; }
};
inline bool operator==(const Token &l, const Token &r)
@@ -178,6 +162,6 @@ namespace Fig
return l.type == r.type and l.value == r.value;
}
static Token IllegalTok(u8"ILLEGAL", TokenType::Illegal);
static Token EOFTok(u8"EOF", TokenType::EndOfFile);
static Token IllegalTok(U"ILLEGAL", TokenType::Illegal);
static Token EOFTok(U"EOF", TokenType::EndOfFile);
} // namespace Fig

View File

@@ -15,53 +15,32 @@ public:
if (!node) return;
switch (node->getType())
{
case AstType::BinaryExpr:
printBinaryExpr(std::static_pointer_cast<BinaryExprAst>(node), indent);
break;
case AstType::UnaryExpr:
printUnaryExpr(std::static_pointer_cast<UnaryExprAst>(node), indent);
break;
case AstType::ValueExpr:
printValueExpr(std::static_pointer_cast<ValueExprAst>(node), indent);
break;
case AstType::VarDefSt:
printVarDef(std::static_pointer_cast<VarDefAst>(node), indent);
break;
case AstType::VarExpr:
printVarExpr(std::static_pointer_cast<VarExprAst>(node), indent);
break;
case AstType::BinaryExpr: printBinaryExpr(std::static_pointer_cast<BinaryExprAst>(node), indent); break;
case AstType::UnaryExpr: printUnaryExpr(std::static_pointer_cast<UnaryExprAst>(node), indent); break;
case AstType::ValueExpr: printValueExpr(std::static_pointer_cast<ValueExprAst>(node), indent); break;
case AstType::VarDefSt: printVarDef(std::static_pointer_cast<VarDefAst>(node), indent); break;
case AstType::VarExpr: printVarExpr(std::static_pointer_cast<VarExprAst>(node), indent); break;
case AstType::BlockStatement:
printBlockStatement(std::static_pointer_cast<BlockStatementAst>(node), indent);
break;
case AstType::FunctionCall:
printFunctionCall(std::static_pointer_cast<FunctionCallExpr>(node), indent);
break;
case AstType::FunctionDefSt:
printFunctionSt(std::static_pointer_cast<FunctionDefSt>(node), indent);
break;
case AstType::IfSt:
printIfSt(std::static_pointer_cast<IfSt>(node), indent);
break;
case AstType::TernaryExpr:
printTernaryExpr(std::static_pointer_cast<TernaryExprAst>(node), indent);
break;
default:
printIndent(indent);
std::cout << "Unknown AST Node\n";
case AstType::FunctionDefSt: printFunctionSt(std::static_pointer_cast<FunctionDefSt>(node), indent); break;
case AstType::IfSt: printIfSt(std::static_pointer_cast<IfSt>(node), indent); break;
case AstType::TernaryExpr: printTernaryExpr(std::static_pointer_cast<TernaryExprAst>(node), indent); break;
default: printIndent(indent); std::cout << "Unknown AST Node\n";
}
}
private:
void printIndent(int indent)
{
std::cout << std::string(indent, ' ');
}
void printIndent(int indent) { std::cout << std::string(indent, ' '); }
void printFString(const Fig::FString &fstr, int indent)
void printFString(const Fig::String &fstr, int indent)
{
printIndent(indent);
std::cout << "FString: \"";
std::cout.write(reinterpret_cast<const char *>(fstr.data()), fstr.size());
std::cout << "String: \"";
std::cout << fstr;
std::cout << "\"\n";
}
@@ -133,10 +112,7 @@ private:
{
printIndent(indent);
std::cout << "BlockStatement\n";
for (const auto &stmt : node->stmts)
{
print(stmt, indent + 2);
}
for (const auto &stmt : node->stmts) { print(stmt, indent + 2); }
}
void printFunctionCall(const std::shared_ptr<FunctionCallExpr> &node, int indent)

View File

@@ -1,7 +1,7 @@
#pragma once
#include <Lexer/lexer.hpp>
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <string>
#include <locale>
#include <cwctype>
@@ -11,36 +11,33 @@
namespace Fig::Utils
{
inline std::vector<FString> splitSource(FString source)
inline std::vector<String> splitSource(const String &source)
{
UTF8Iterator it(source);
std::vector<FString> lines;
FString currentLine;
while (!it.isEnd())
std::vector<String> lines;
String currentLine;
for (char32_t c : source)
{
UTF8Char c = *it;
if (c == U'\n')
{
lines.push_back(currentLine);
currentLine = FString(u8"");
currentLine = String(U"\1");
}
else
{
currentLine += c.getString();
currentLine += c;
}
++it;
}
if (!currentLine.empty())
{
lines.push_back(currentLine);
}
if (!currentLine.empty()) { lines.push_back(currentLine); }
return lines;
}
inline std::u32string utf8ToUtf32(const FString &s)
inline std::u32string utf8ToUtf32(const String &s)
{
std::u32string result;
size_t i = 0;
while (i < s.size())
while (i < s.length())
{
char32_t codepoint = 0;
unsigned char c = static_cast<unsigned char>(s[i]);
@@ -57,12 +54,15 @@ namespace Fig::Utils
}
else if ((c >> 4) == 0xE)
{
codepoint = ((c & 0x0F) << 12) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 6) | (static_cast<unsigned char>(s[i + 2]) & 0x3F);
codepoint = ((c & 0x0F) << 12) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 6)
| (static_cast<unsigned char>(s[i + 2]) & 0x3F);
i += 3;
}
else if ((c >> 3) == 0x1E)
{
codepoint = ((c & 0x07) << 18) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 12) | ((static_cast<unsigned char>(s[i + 2]) & 0x3F) << 6) | (static_cast<unsigned char>(s[i + 3]) & 0x3F);
codepoint = ((c & 0x07) << 18) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 12)
| ((static_cast<unsigned char>(s[i + 2]) & 0x3F) << 6)
| (static_cast<unsigned char>(s[i + 3]) & 0x3F);
i += 4;
}
else
@@ -75,59 +75,6 @@ namespace Fig::Utils
return result;
}
inline FString utf32ToUtf8(const std::u32string &s)
{
FString result;
for (char32_t cp : s)
{
if (cp < 0x80)
{
result.push_back(static_cast<char8_t>(cp));
}
else if (cp < 0x800)
{
result.push_back(static_cast<char8_t>((cp >> 6) | 0xC0));
result.push_back(static_cast<char8_t>((cp & 0x3F) | 0x80));
}
else if (cp < 0x10000)
{
result.push_back(static_cast<char8_t>((cp >> 12) | 0xE0));
result.push_back(static_cast<char8_t>(((cp >> 6) & 0x3F) | 0x80));
result.push_back(static_cast<char8_t>((cp & 0x3F) | 0x80));
}
else
{
result.push_back(static_cast<char8_t>((cp >> 18) | 0xF0));
result.push_back(static_cast<char8_t>(((cp >> 12) & 0x3F) | 0x80));
result.push_back(static_cast<char8_t>(((cp >> 6) & 0x3F) | 0x80));
result.push_back(static_cast<char8_t>((cp & 0x3F) | 0x80));
}
}
return result;
}
inline FString toLower(const FString &s)
{
std::u32string u32 = utf8ToUtf32(s);
std::locale loc("");
for (auto &ch : u32)
{
ch = std::towlower(ch);
}
return utf32ToUtf8(u32);
}
inline FString toUpper(const FString &s)
{
std::u32string u32 = utf8ToUtf32(s);
std::locale loc("");
for (auto &ch : u32)
{
ch = std::towupper(ch);
}
return utf32ToUtf8(u32);
}
template <class T>
bool vectorContains(const T &t, const std::vector<T> v)
{

View File

@@ -24,10 +24,7 @@ namespace Fig
uint64_t base = currentFrame->base;
popFrame();
if (frames.empty())
{
return ret;
}
if (frames.empty()) { return ret; }
stack.resize(base); // 清除函数的临时值
push(ret);
@@ -147,7 +144,8 @@ namespace Fig
if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
{
ValueType::DoubleClass result = (double)lhs.as<ValueType::IntClass>() / (double)rhs.as<ValueType::IntClass>();
ValueType::DoubleClass result =
(double) lhs.as<ValueType::IntClass>() / (double) rhs.as<ValueType::IntClass>();
push(Object(result));
break;
}
@@ -166,12 +164,7 @@ namespace Fig
case OpCode::JUMP_IF_FALSE: {
const Object &cond = pop();
if (!cond.is<bool>())
{
throw RuntimeError(
FString(u8"Condition must be boolean!")
);
}
if (!cond.is<bool>()) { throw RuntimeError(String(U"\1")); }
if (!cond.as<bool>())
{
// cond is falsity
@@ -181,14 +174,13 @@ namespace Fig
break;
}
case OpCode::CALL:
{
case OpCode::CALL: {
uint16_t argCount = static_cast<uint16_t>(ins.operand); // number of max arg is UINT16_MAX
const Object &obj = stack.back();
if (!obj.is<Function>())
{
throw RuntimeError(FString(std::format("{} is not callable", obj.toString().toBasicString())));
throw RuntimeError(String(std::format("{} is not callable", obj.toString().toBasicString())));
}
// const Function &fn_obj = obj.as<Function>();
@@ -203,17 +195,11 @@ namespace Fig
pop(); // pop function
for (int64_t i = 0; i < fn.slotCount - argCount; ++i)
{
push(*Object::getNullInstance());
}
for (int64_t i = 0; i < fn.slotCount - argCount; ++i) { push(*Object::getNullInstance()); }
CallFrame newFrame
{
0,
base, // 参数已经加载到stack, base为第一个参数
fn
};
CallFrame newFrame{0,
base, // 参数已经加载到stack, base为第一个参数
fn};
addFrame(newFrame);
break;

View File

@@ -1,26 +1,37 @@
/*
███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████ █████████ █████ █████ █████████ █████████ ██████████
░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███ ███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███░░███ ░░███ ███░░░░░███ ███░░░░░███░░███░░░░░
░ ░███ ░ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░███░███ ░███ ███ ░░░ ░███ ███ ░███ ░███ ███ ░░░ ░███ █
░███ ░███████████ ░█████ ░██████ ░███ ░███ ░███ ░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████
░███ ░███░░░░░███ ░███░░█ ░███░░░█ ░███ ░███ █████ ░███ ░███░░░░░███ ░███ ░░██████ ░███ █████ ░███ ░███ ░███░░░░░███ ░███ █████ ░███░░█
░███ ░███ ░███ ░███ ░ █ ░███ ░ ░███░███ ░███ ░███ ░███ ░███ ░███ ░░█████ ░░███ ███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███
█████ █████ █████ ██████████ █████ █████ ░░█████████ ███████████ █████ █████ █████ ░█████ ░░█████████ ░░████████ █████ █████ ░░█████████ ██████████
░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░
███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████
█████████ █████ █████ █████████ █████████ ██████████ ░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███
███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░███ ███░░░░░███░███ ░███ ███░░░░███ ███░░░░░███░░███░░░░░█
░███ ░███ ░███ ░███ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░██████ ░███ ███
░░░ ░███ ░███ ░███ ░███ ███ ░░░ ░███ █ ░ ░███ ░███████████ ░██████ ░██████ ░███ ███ ░███
░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████ ░███ ░███░░░░███ ░███░░
░███░░░███ ░███ █████ ███ ███░░░░░███ ░███ ░░██████ ███ █████ ░███ ░███ ░███░░░░░███ ░███
█████ ░███░░█ ░███ ░███ ░███ ░███ ███ ░ ░███ ░░███ ░░███ ░███ █ ░███ ░███ ░███
░░█████ ░░███ ░░███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░ █ █████ █████ █████ ██████████ █████
█████ ░░█████████ ███████████ █████ █████ █████ ░░█████ ░░█████████ ░░████████ █████ █████ ░░█████████
██████████ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░
░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░
.---.
. __.....__ .--. | | _..._ __.....__
.'| .-'' '. _.._ |__| .--./) | | .' '. .--./) .--./) .-'' '.
.| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\ /.''\\ / .-''"'-. `.
.' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | | __ | | | |/ /________\ \
.' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _ _ .:--.'. \`-' / | |
'--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | ' / | / | \ | /("'` \ .-------------'
| | | / | | \ '-.____...---. | | | | \ '---. | |`" __ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---.
| | | | | | `. .' | | |__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .'
| '.'| | | | `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / | |_|| || `''-...... -'
| / | '. | '. | | \'. __// \ \._,\ '/| | | | \'. __// ' .'| '/\ \._,\ '/\'. __//
`'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---' `-' `--' `--' `" `'---'
. __.....__ .--. | | _..._ __.....__
.'| .-'' '. _.._ |__| .--./) | | .' '. .--./)
.--./) .-'' '.
.| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\
/.''\\ / .-''"'-. `.
.' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | |
__ | | | |/ /________\ \
.' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _
_ .:--.'. \`-' / | |
'--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | '
/ | / | \ | /("'` \ .-------------' | | | / | | \ '-.____...---. | | | | \ '---. | |`"
__ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---. | | | | | | `. .' | |
|__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .' | '.'| | |
| `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / |
|_|| || `''-...... -' | / | '. | '. | | \'. __// \ \._,\ '/| | | |
\'. __// ' .'| '/\ \._,\ '/\'. __//
`'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---'
`-' `--' `--' `" `'---'
Copyright (C) 2020-2026 PuqiAR
@@ -44,21 +55,14 @@ This software is licensed under the MIT License. See LICENSE.txt for details.
static size_t addressableErrorCount = 0;
static size_t unaddressableErrorCount = 0;
int main(int argc, char **argv)
{
Time::init();
// init, set start_time (std::chrono::time_point)
argparse::ArgumentParser program("Fig Interpreter", Fig::Core::VERSION.data());
program.add_argument("source")
.help("source file to be interpreted")
.default_value(std::string(""));
program.add_argument("-r", "--repl")
.help("start repl")
.default_value(false)
.implicit_value(true);
program.add_argument("source").help("source file to be interpreted").default_value(std::string(""));
program.add_argument("-r", "--repl").help("start repl").default_value(false).implicit_value(true);
// program.add_argument("-v", "--version")
// .help("get the version of Fig Interpreter")
// .default_value(false)
@@ -87,7 +91,7 @@ int main(int argc, char **argv)
exit(0);
}
Fig::FString sourcePath(program.get<std::string>("source"));
Fig::String sourcePath(program.get<std::string>("source"));
if (sourcePath.empty())
{
std::cerr << "No source file provided.\n";
@@ -102,9 +106,9 @@ int main(int argc, char **argv)
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
std::vector<FString> sourceLines = Fig::Utils::splitSource(Fig::FString(source));
std::vector<String> sourceLines = Fig::Utils::splitSource(Fig::String(source));
Fig::Lexer lexer((Fig::FString(source)), sourcePath, sourceLines);
Fig::Lexer lexer((Fig::String(source)), sourcePath, sourceLines);
// Token tok;
// while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile)

View File

@@ -27,6 +27,7 @@ end
add_files("src/Core/warning.cpp")
add_files("src/Core/runtimeTime.cpp")
add_files("src/Core/String.cpp")
add_files("src/Lexer/lexer.cpp")
add_files("src/Parser/parser.cpp")
@@ -63,3 +64,11 @@ target("ir_test_main")
add_files("src/IR/ir_test_main.cpp")
set_warnings("all")
target("StringTest")
set_kind("binary")
add_files("src/Core/StringTest.cpp")
set_warnings("all")