1 Commits

Author SHA1 Message Date
9c68b2e77d 尝试UTF32String 2026-02-05 22:20:21 +08:00
92 changed files with 3269 additions and 3484 deletions

View File

@@ -1,30 +0,0 @@
import std.io;
struct Point
{
x: Int; // type specifiers are optional
y: Int; // type specifiers are optional
// x and y are private fields, can only reached by internal context
public func toString() -> String
{
return "(" + (x as String) + "," + (y as String) + ")";
}
// public func toString() {} is ok
}
// make points
var p1 := new Point{1, 2};
io.println(p1.toString()); // (1,2)
var p2 := new Point{x: 2, y: 3};
io.println(p2.toString()); // (2,3)
var x := 114;
var y := 514;
var p3 := new Point{y, x}; // shorthand mode, can be unordered, auto match field and variable!
// = Point{x: x, y: y}
io.println(p3.toString()); // (114,514)

View File

@@ -1,94 +0,0 @@
import std.io;
interface Document
{
getDepth() -> Int; // return type is necessary
getName() -> String;
/* toString() -> String
{
// default implementation
}
*/
}
struct File
{
public depth: Int;
public name: String;
}
impl Document for File
{
getDepth()
{
return depth;
}
getName()
{
return name;
}
}
struct Folder
{
public depth: Int;
public name: String;
public childs: List = [];
}
impl Document for Folder
{
getDepth()
{
return depth;
}
getName()
{
return name;
}
}
const root_folder := new Folder{
0,
"root",
[
new File{
1,
"joyo.txt"
},
new Folder{
2,
"joyoyo",
[
new File{
3,
"JOYO2.txt"
},
new Folder{
3,
"joyoyoyo"
},
]
}
]
};
func print_directory(root: Document)
{
io.print(" " * root.getDepth());
io.println(root.getDepth(), root.getName());
if root is Folder
{
for var i := 0; i < root.childs.length(); i += 1
{
var child := root.childs[i];
print_directory(child);
}
}
}
print_directory(root_folder);

View File

@@ -6,6 +6,6 @@ def fib(x:int) -> int:
if __name__ == '__main__': if __name__ == '__main__':
t0 = tt() t0 = tt()
result = fib(30) result = fib(25)
t1 = tt() t1 = tt()
print('cost: ',t1-t0, 'result:', result) print('cost: ',t1-t0, 'result:', result)

View File

@@ -42,7 +42,7 @@ def resolveInstallPath(os: int):
return default_path[os] return default_path[os]
def getReleases(): def getReleases():
api_postfix = '/api/v1/repos/PuqiAR/Fig-TreeWalker/releases' api_postfix = '/api/v1/repos/PuqiAR/Fig/releases'
api_url = GITEA_URL + api_postfix api_url = GITEA_URL + api_postfix
rel = requests.get(api_url).text rel = requests.get(api_url).text

View File

@@ -35,13 +35,13 @@ Recommend view on Gitea Endpoint
1. Clone the repository: 1. Clone the repository:
```bash ```bash
git clone https://git.fig-lang.cn/PuqiAR/Fig-TreeWalker.git git clone https://git.fig-lang.cn/PuqiAR/Fig.git
# Recommend # Recommend
``` ```
or or
```bash ```bash
git clone https://github.com/PuqiAR/Fig-TreeWalker.git git clone https://github.com/PuqiAR/Fig.git
``` ```
2. Navigate to the project directory: 2. Navigate to the project directory:
@@ -77,32 +77,6 @@ Replace `[file]` with the path to your input file.
## Performance Summary ## Performance Summary
**Version:** 0.4.3-alpha (Tree-walker Interpreter)
**Test Hardware:** i5-13490F, Windows 11
**Execution Times for Fibonacci(30):**
* Naive Recursion: **5.47s** (~2.14× faster than 0.4.2-alpha)
* Memoization: **0.55ms** (~1.69× faster than 0.4.2-alpha)
* Iteration: **0.10ms** (~3.73× faster than 0.4.2-alpha)
* Tail Recursion: **0.16ms** (~2.55× faster than 0.4.2-alpha)
**Visual Comparison:**
```
Naive Recursion : █████████████████████████ 5.47s
Memoization : ▉ 0.55ms
Iteration : ▍ 0.10ms
Tail Recursion : ▎ 0.16ms
```
**Key Insight:** Algorithm choice still dominates performance, while 0.4.3-alpha shows significant improvements in function call and loop efficiency.
**Detailed Reports:** [English](./docs/benchmark_result/0.4.3-alpha/benchmark_result_en_0.4.3-alpha.pdf) | [中文](./docs/benchmark_result/0.4.3-alpha/benchmark_result_zh_0.4.3-alpha.pdf)
---
## Older version reports...
**Version:** 0.4.2-alpha (Tree-walker Interpreter) **Version:** 0.4.2-alpha (Tree-walker Interpreter)
**Test Hardware:** i5-13490F, Windows 11 **Test Hardware:** i5-13490F, Windows 11
@@ -122,7 +96,7 @@ Tail Recursion : ▎ 0.40ms
**Key Insight:** Algorithm choice dominates performance in this tree-walker implementation. **Key Insight:** Algorithm choice dominates performance in this tree-walker implementation.
**Detailed Reports:** [English](./docs/benchmark_result/0.4.2-alpha/benchmark_result_en_0.4.2-alpha.pdf) | [中文](./docs/benchmark_result/0.4.2-alpha/benchmark_result_zh_0.4.2-alpha.pdf) **Detailed Reports:** [English](./docs/benchmark_result/benchmark_result_en_0.4.2-alpha.md) | [中文](./docs/benchmark_result/benchmark_result_zh_0.4.2-alpha.md)
## Language Documents ## Language Documents

View File

@@ -27,13 +27,13 @@
1. 克隆存储库: 1. 克隆存储库:
```bash ```bash
git clone https://git.fig-lang.cn/PuqiAR/Fig-TreeWalker.git git clone https://git.fig-lang.cn/PuqiAR/Fig.git
# 推荐 # 推荐
``` ```
```bash ```bash
git clone https://github.com/PuqiAR/Fig-TreeWalker.git git clone https://github.com/PuqiAR/Fig.git
``` ```
@@ -66,33 +66,6 @@ Fig 围绕几个核心原则设计:
## 性能概览 ## 性能概览
**版本:** 0.4.3-alpha (树遍历解释器)
**测试硬件:** i5-13490F, Windows 11
**计算 Fibonacci(30) 的执行时间:**
* 朴素递归: **5.47秒** (~比0.4.2-alpha快2.14倍)
* 记忆化: **0.55毫秒** (~比0.4.2-alpha快1.69倍)
* 迭代: **0.10毫秒** (~比0.4.2-alpha快3.73倍)
* 尾递归: **0.16毫秒** (~比0.4.2-alpha快2.55倍)
**可视化对比:**
```
朴素递归 : █████████████████████████ 5.47秒
记忆化递归 : ▉ 0.55毫秒
迭代算法 : ▍ 0.10毫秒
尾递归 : ▎ 0.16毫秒
```
**核心发现:** 算法选择仍然主导性能,同时 0.4.3-alpha 在函数调用和循环效率上有明显提升。
**详细报告:** [English](./docs/benchmark_result/0.4.3-alpha/benchmark_result_en_0.4.3-alpha.pdf) | [中文](./docs/benchmark_result/0.4.3-alpha/benchmark_result_zh_0.4.3-alpha.pdf)
---
## 旧版本报告...
**版本:** 0.4.2-alpha (树遍历解释器) **版本:** 0.4.2-alpha (树遍历解释器)
**测试硬件:** i5-13490F, Windows 11 **测试硬件:** i5-13490F, Windows 11
@@ -112,7 +85,7 @@ Fig 围绕几个核心原则设计:
**核心发现:** 在此树遍历实现中,算法选择主导性能表现。 **核心发现:** 在此树遍历实现中,算法选择主导性能表现。
**详细报告:** [English](./docs/benchmark_result/0.4.2-alpha/benchmark_result_en_0.4.2-alpha.pdf) | [中文](./docs/benchmark_result/0.4.2-alpha/benchmark_result_zh_0.4.2-alpha.pdf) **详细报告:** [English](./docs/benchmark_result/benchmark_result_en_0.4.2-alpha.md) | [中文](./docs/benchmark_result/benchmark_result_zh_0.4.2-alpha.md)
## 语言文档 ## 语言文档

View File

@@ -1,163 +0,0 @@
# Fig Language Performance Benchmark Report
## Version: 0.4.3-alpha (Tree Traversal Interpreter)
### Preface
This report presents benchmark tests of Fibonacci algorithms in Fig v0.4.3-alpha tree traversal interpreter, compared with version 0.4.2-alpha. Results show significant performance improvements in function calls, loops, and recursion optimizations in 0.4.3-alpha, especially in iterative and tail-recursive implementations.
### Test Environment
* **CPU:** Intel Core i5-13490F
* **Operating System:** Windows 11
* **Interpreter:** Fig Tree Traversal Interpreter v0.4.3-alpha
* **Test Date:** Current execution
### Executive Summary
This benchmark evaluates four different Fibonacci algorithm implementations in Fig, computing the 30th Fibonacci number (832,040). Algorithm choice remains the dominant factor for performance, while interpreter improvements in function call and loop efficiency are also reflected.
## Performance Results
### Latest Floating Execution Time (0.4.3-alpha)
| Algorithm | Time (s) | Time (ms) | Relative Speed |
| --------------------------- | ----------- | ---------- | ---------------- |
| `fib` (Naive Recursion) | 5.471 s | 5471.37 ms | 1.00× (baseline) |
| `fib_memo` (Memoization) | 0.0005503 s | 0.5503 ms | 9,950× faster |
| `fib_iter` (Iterative) | 0.0001004 s | 0.1004 ms | 54,500× faster |
| `fib_tail` (Tail Recursion) | 0.0001573 s | 0.1573 ms | 34,800× faster |
### Comparison with 0.4.2-alpha
| Algorithm | 0.4.2-alpha Time | 0.4.3-alpha Time | Performance Gain |
| --------------------------- | ---------------- | ---------------- | ---------------- |
| `fib` (Naive Recursion) | 11.721 s | 5.471 s | ~2.14× |
| `fib_memo` (Memoization) | 0.930 ms | 0.550 ms | ~1.69× |
| `fib_iter` (Iterative) | 0.375 ms | 0.100 ms | ~3.73× |
| `fib_tail` (Tail Recursion) | 0.401 ms | 0.157 ms | ~2.55× |
---
## Visual Performance Comparison (Horizontal Bar Placeholder)
0.4.2-alpha vs 0.4.3-alpha
**Note:** Each line contains two bars: gray for 0.4.2-alpha, blue for 0.4.3-alpha
<table>
<tr>
<th>Algorithm</th><th>Performance Comparison</th>
</tr>
<tr>
<td>fib</td>
<td>
<span style="display:inline-block; background-color:#555555; width:350px; height:20px;"></span>
<span style="display:inline-block;"> 11.72 s</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:165px; height:20px;"></span>
<span style="display:inline-block;"> 5.47 s</span>
</td>
</tr>
<tr>
<td>fib_memo</td>
<td>
<span style="display:inline-block; background-color:#555555; width:28px; height:20px;"></span>
<span style="display:inline-block;"> 0.93 ms</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:17px; height:20px;"></span>
<span style="display:inline-block;"> 0.55 ms</span>
</td>
</tr>
<tr>
<td>fib_iter</td>
<td>
<span style="display:inline-block; background-color:#555555; width:11px; height:20px;"></span>
<span style="display:inline-block;"> 0.375 ms</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:3px; height:20px;"></span>
<span style="display:inline-block;"> 0.100 ms</span>
</td>
</tr>
<tr>
<td>fib_tail</td>
<td>
<span style="display:inline-block; background-color:#555555; width:12px; height:20px;"></span>
<span style="display:inline-block;"> 0.401 ms</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:5px; height:20px;"></span>
<span style="display:inline-block;"> 0.157 ms</span>
</td>
</tr>
</table>
---
## Detailed Analysis
### 1. Naive Recursion (`fib`)
* **Time:** 5.471 seconds (5471 ms)
* **Algorithm Complexity:** O(2ⁿ) exponential
* **Performance Notes:**
* Reduced by roughly half compared to 0.4.2-alpha
* Function call overhead optimization effective, but exponential growth remains the bottleneck
### 2. Memoized Recursion (`fib_memo`)
* **Time:** 0.550 ms
* **Algorithm Complexity:** O(n) linear
* **Performance Notes:**
* Hash table / cache access efficiency improved
* Sub-millisecond execution suitable for overlapping subproblems
### 3. Iterative (`fib_iter`)
* **Time:** 0.100 ms
* **Algorithm Complexity:** O(n) linear
* **Performance Notes:**
* Fastest implementation, ~3.7× improvement over 0.4.2-alpha
* Loop and arithmetic operation optimization significant
### 4. Tail Recursion (`fib_tail`)
* **Time:** 0.157 ms
* **Algorithm Complexity:** O(n) linear
* **Performance Notes:**
* Slightly slower than iterative, ~2.5× improvement over 0.4.2-alpha
* Tree traversal interpreter optimizations for recursion effective; TCO not implemented
---
## Technical Insights
* Function call overhead significantly reduced
* Loop and arithmetic operations show greatest efficiency gains
* Hash table / cache access highly efficient
* Algorithm choice remains the dominant factor for performance
---
## Recommendations for Developers
1. Prioritize iterative solutions for performance-critical code
2. Use memoization for recursion with overlapping subproblems
3. Tail recursion is suitable for moderate depth, but TCO is not implemented
4. Avoid exponential algorithms in interpreted code
5. Benchmark different implementations, as algorithm choice dominates performance
---
## Conclusion
Fig v0.4.3-alpha tree traversal interpreter shows significant improvements in function call and loop optimizations, particularly benefiting iterative and tail-recursive implementations.
O(n) algorithms execute at sub-millisecond speeds, while exponential recursion remains limited. Overall interpreter performance is adequate for practical applications.
**Report Generated:** Based on actual benchmark execution
**Interpreter Type:** Tree Traversal Interpreter
**Version:** 0.4.3-alpha

View File

@@ -1,161 +0,0 @@
# Fig 语言性能基准测试报告
## 版本: 0.4.3-alpha (树遍历解释器)
### 前言
本报告基于 Fig v0.4.3-alpha 树遍历解释器对 Fibonacci 算法进行了基准测试,并与 0.4.2-alpha 版本对比。结果显示 0.4.3-alpha 在函数调用、循环和递归优化方面都有显著提升,尤其是迭代和尾递归实现性能改善明显。
### 测试环境
* **CPU:** Intel Core i5-13490F
* **操作系统:** Windows 11
* **编译器/解释器:** Fig 树遍历解释器 v0.4.3-alpha
* **测试日期:** 当前测试执行
### 执行摘要
本基准测试评估了 Fig 中四种不同斐波那契算法实现的性能计算第30个斐波那契数832,040。结果显示算法选择仍是性能主导因素同时反映了解释器在函数调用和循环方面的优化效果。
## 性能结果
### 最新浮动执行时间 (0.4.3-alpha)
| 算法 | 时间(秒) | 时间(毫秒) | 相对速度 |
| ------------------- | ----------- | ---------- | ------------ |
| `fib` (朴素递归) | 5.471 s | 5471.37 ms | 1.00× (基准) |
| `fib_memo` (记忆化) | 0.0005503 s | 0.5503 ms | 9,950× 更快 |
| `fib_iter` (迭代) | 0.0001004 s | 0.1004 ms | 54,500× 更快 |
| `fib_tail` (尾递归) | 0.0001573 s | 0.1573 ms | 34,800× 更快 |
### 与 0.4.2-alpha 对比
| 算法 | 0.4.2-alpha 时间 | 0.4.3-alpha 时间 | 性能提升倍数 |
| ------------------- | ---------------- | ---------------- | ------------ |
| `fib` (朴素递归) | 11.721 s | 5.471 s | ~2.14× |
| `fib_memo` (记忆化) | 0.930 ms | 0.550 ms | ~1.69× |
| `fib_iter` (迭代) | 0.375 ms | 0.100 ms | ~3.73× |
| `fib_tail` (尾递归) | 0.401 ms | 0.157 ms | ~2.55× |
---
## 可视化性能对比(横向柱状图占位符)
0.4.2-alpha vs 0.4.3-alpha
**说明:** 每行两条条形:灰色表示 0.4.2-alpha蓝色表示 0.4.3-alpha
<table>
<tr>
<th>算法</th><th>性能对比</th>
</tr>
<tr>
<td>fib</td>
<td>
<span style="display:inline-block; background-color:#555555; width:350px; height:20px;"></span>
<span style="display:inline-block;"> 11.72 s</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:165px; height:20px;"></span>
<span style="display:inline-block;"> 5.47 s</span>
</td>
</tr>
<tr>
<td>fib_memo</td>
<td>
<span style="display:inline-block; background-color:#555555; width:28px; height:20px;"></span>
<span style="display:inline-block;"> 0.93 ms</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:17px; height:20px;"></span>
<span style="display:inline-block;"> 0.55 ms</span>
</td>
</tr>
<tr>
<td>fib_iter</td>
<td>
<span style="display:inline-block; background-color:#555555; width:11px; height:20px;"></span>
<span style="display:inline-block;"> 0.375 ms</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:3px; height:20px;"></span>
<span style="display:inline-block;"> 0.100 ms</span>
</td>
</tr>
<tr>
<td>fib_tail</td>
<td>
<span style="display:inline-block; background-color:#555555; width:12px; height:20px;"></span>
<span style="display:inline-block;"> 0.401 ms</span><br>
<span style="display:inline-block; background-color:#1E90FF; width:5px; height:20px;"></span>
<span style="display:inline-block;"> 0.157 ms</span>
</td>
</tr>
</table>
## 详细分析
### 1. 朴素递归实现 (`fib`)
* **时间:** 5.471 秒 (5471 毫秒)
* **算法复杂度:** O(2ⁿ) 指数级
* **性能说明:**
* 相比 0.4.2-alpha 减少约一半
* 函数调用开销优化有效,但指数增长仍是瓶颈
### 2. 记忆化递归实现 (`fib_memo`)
* **时间:** 0.550 毫秒
* **算法复杂度:** O(n) 线性
* **性能说明:**
* 哈希表/缓存访问效率进一步提高
* 亚毫秒级执行,适合重叠子问题
### 3. 迭代实现 (`fib_iter`)
* **时间:** 0.100 毫秒
* **算法复杂度:** O(n) 线性
* **性能说明:**
* 最快实现,比 0.4.2-alpha 提升 3.7 倍
* 循环和算术操作优化显著
### 4. 尾递归实现 (`fib_tail`)
* **时间:** 0.157 毫秒
* **算法复杂度:** O(n) 线性
* **性能说明:**
* 相比迭代略慢,但比 0.4.2-alpha 提升 2.5 倍
* 树遍历解释器对递归调用优化有效TCO 未实现
---
## 技术洞察
* 函数调用开销显著下降
* 循环和算术操作效率提升最大
* 哈希表/缓存访问效率高
* 算法选择仍是性能主导
---
## 给开发者的建议
1. 性能关键代码优先迭代
2. 重叠子问题递归使用记忆化
3. 尾递归可用于中等深度,但 TCO 未实现
4. 避免指数算法
5. 基准测试不同实现,算法选择主导性能
---
## 结论
Fig v0.4.3-alpha 树遍历解释器在函数调用和循环优化上有显著提升,尤其是迭代和尾递归实现性能改善明显。
O(n) 算法执行亚毫秒级,指数递归仍受限,但整体解释器性能在实际应用中已足够优秀。
**报告生成时间:** 基于实际基准测试执行
**解释器类型:** 树遍历解释器
**版本:** 0.4.3-alpha

View File

@@ -162,9 +162,9 @@ Fig 语言的关键字包括:
| -------- | ----------------------------------------------------------- | | -------- | ----------------------------------------------------------- |
| 声明 | `func`, `var`, `const`, `struct`, `interface`, `import` | | 声明 | `func`, `var`, `const`, `struct`, `interface`, `import` |
| 控制流 | `if`, `else`, `while`, `for`, `return`, `break`, `continue` | | 控制流 | `if`, `else`, `while`, `for`, `return`, `break`, `continue` |
| 错误处理 | `try`, `catch`, `throw`, `finally` | | 错误处理 | `try`, `catch`, `throw`, `Finally` |
| 逻辑运算 | `and`, `or`, `not` | | 逻辑运算 | `and`, `or`, `not` |
| 类型相关 | `is`, `as`, `impl`, `new`, `public` | | 类型相关 | `is`, `impl`, `new`, `public` |
这些关键字不能用作标识符名称。 这些关键字不能用作标识符名称。

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,34 +9,26 @@ namespace Fig::Ast
public: public:
Expression value; Expression value;
ThrowSt() ThrowSt() { type = AstType::ThrowSt; }
{
type = AstType::ThrowSt;
}
ThrowSt(Expression _value) : ThrowSt(Expression _value) : value(std::move(_value)) { type = AstType::ThrowSt; }
value(std::move(_value))
{
type = AstType::ThrowSt;
}
}; };
using Throw = std::shared_ptr<ThrowSt>; using Throw = std::shared_ptr<ThrowSt>;
struct Catch struct Catch
{ {
FString errVarName; String errVarName;
bool hasType = false; bool hasType = false;
FString errVarType; String errVarType;
BlockStatement body; BlockStatement body;
Catch() {} 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)) errVarName(std::move(_errVarName)), errVarType(std::move(_errVarType)), body(std::move(_body))
{ {
hasType = true; hasType = true;
} }
Catch(FString _errVarName, BlockStatement _body) : Catch(String _errVarName, BlockStatement _body) : errVarName(std::move(_errVarName)), body(std::move(_body))
errVarName(std::move(_errVarName)), body(std::move(_body))
{ {
hasType = false; hasType = false;
} }
@@ -49,10 +41,7 @@ namespace Fig::Ast
std::vector<Catch> catches; std::vector<Catch> catches;
BlockStatement finallyBlock = nullptr; BlockStatement finallyBlock = nullptr;
TrySt() TrySt() { type = AstType::TrySt; }
{
type = AstType::TrySt;
}
TrySt(BlockStatement _body, std::vector<Catch> _catches, BlockStatement _finallyBlock) : TrySt(BlockStatement _body, std::vector<Catch> _catches, BlockStatement _finallyBlock) :
body(std::move(_body)), catches(std::move(_catches)), finallyBlock(std::move(_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 class FunctionDefSt final : public StatementAst // for definition
{ {
public: public:
FString name; String name;
FunctionParameters paras; FunctionParameters paras;
bool isPublic; bool isPublic;
Expression retType; Expression retType;
BlockStatement body; BlockStatement body;
FunctionDefSt() FunctionDefSt() { type = AstType::FunctionDefSt; }
{ FunctionDefSt(
type = AstType::FunctionDefSt; String _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body)
}
FunctionDefSt(FString _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body)
{ {
type = AstType::FunctionDefSt; type = AstType::FunctionDefSt;
@@ -42,4 +40,4 @@ namespace Fig::Ast
} }
}; };
using FunctionDef = std::shared_ptr<FunctionDefSt>; using FunctionDef = std::shared_ptr<FunctionDefSt>;
}; // namespace Fig }; // namespace Fig::Ast

View File

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

View File

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

View File

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

View File

@@ -3,69 +3,49 @@
#include <Ast/functionParameters.hpp> #include <Ast/functionParameters.hpp>
#include <Ast/astBase.hpp> #include <Ast/astBase.hpp>
namespace Fig::Ast namespace Fig::Ast
{ {
/* /*
interface Readable interface Readable
{ {
read() -> String read() -> String
{ {
// default // default
} }
flush() -> Null; // non-default flush() -> Null; // non-default
} }
*/
*/
struct InterfaceMethod struct InterfaceMethod
{ {
FString name; String name;
FunctionParameters paras; FunctionParameters paras;
Expression returnType; Expression returnType;
BlockStatement defaultBody = nullptr; // nullptr is non-default func BlockStatement defaultBody = nullptr; // nullptr is non-default func
bool hasDefaultBody() const bool hasDefaultBody() const { return defaultBody != nullptr; }
{
return defaultBody != nullptr;
}
}; };
/*
interface IO : Writable + Readable
{
}
interface XX
{
}
*/
class InterfaceDefAst final : public StatementAst class InterfaceDefAst final : public StatementAst
{ {
public: public:
FString name; String name;
std::vector<Expression> bundles;
std::vector<InterfaceMethod> methods; std::vector<InterfaceMethod> methods;
std::vector<FString> parents; // Feature, NOT NOW std::vector<String> parents; // Feature, NOT NOW
bool isPublic; bool isPublic;
InterfaceDefAst() InterfaceDefAst() { type = AstType::InterfaceDefSt; }
{
type = AstType::InterfaceDefSt;
}
InterfaceDefAst(FString _name, std::vector<Expression> _bundles, std::vector<InterfaceMethod> _methods, bool _isPublic) : InterfaceDefAst(String _name, std::vector<InterfaceMethod> _methods, bool _isPublic) :
name(std::move(_name)), bundles(std::move(_bundles)), methods(std::move(_methods)), isPublic(_isPublic) name(std::move(_name)), methods(std::move(_methods)), isPublic(_isPublic)
{ {
type = AstType::InterfaceDefSt; type = AstType::InterfaceDefSt;
} }
}; };
using InterfaceDef = std::shared_ptr<InterfaceDefAst>; using InterfaceDef = std::shared_ptr<InterfaceDefAst>;
}; }; // namespace Fig::Ast

View File

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

View File

@@ -10,8 +10,8 @@ namespace Fig::Ast
public: public:
bool isPublic; bool isPublic;
bool isConst; bool isConst;
FString name; String name;
// FString typeName; // String typeName;
Expression declaredType; Expression declaredType;
Expression expr; Expression expr;
@@ -24,7 +24,8 @@ namespace Fig::Ast
expr = nullptr; expr = nullptr;
followupType = false; 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; type = AstType::VarDefSt;
isPublic = _isPublic; isPublic = _isPublic;
@@ -37,4 +38,4 @@ namespace Fig::Ast
}; };
using VarDef = std::shared_ptr<VarDefAst>; using VarDef = std::shared_ptr<VarDefAst>;
} // namespace Fig } // namespace Fig::Ast

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Bytecode/Instruction.hpp> #include <Bytecode/Instruction.hpp>
#include <Evaluator/Value/value.hpp> #include <Evaluator/Value/value.hpp>
@@ -10,16 +10,16 @@ namespace Fig
{ {
struct ChunkAddressInfo struct ChunkAddressInfo
{ {
FString sourcePath; String sourcePath;
std::vector<FString> sourceLines; std::vector<String> sourceLines;
}; };
struct Chunk struct Chunk
{ {
Instructions ins; // vector<Instruction> Instructions ins; // vector<Instruction>
std::vector<Object> constants; // 常量池 std::vector<Object> constants; // 常量池
std::vector<InstructionAddressInfo> instructions_addr; // 下标和ins对齐表示每个Instruction对应的地址 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; using AddressableError::AddressableError;
virtual FString toString() const override virtual String toString() const override
{ {
std::string msg = std::format("[CompileError] {} in [{}] {}", std::string msg = std::format("[CompileError] {} in [{}] {}",
this->message.toBasicString(), this->message.toBasicString(),
this->src_loc.file_name(), this->src_loc.file_name(),
this->src_loc.function_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 struct CompiledFunction
{ {
Chunk chunk; // 函数代码块 Chunk chunk; // 函数代码块
FString name; // 函数名 String name; // 函数名
uint64_t posArgCount; // 位置参数数量 uint64_t posArgCount; // 位置参数数量
uint64_t defArgCount; // 默认参数数量 uint64_t defArgCount; // 默认参数数量
bool variadicPara; // 可变参数(是:最后为可变,否:不可变) bool variadicPara; // 可变参数(是:最后为可变,否:不可变)
uint64_t localCount; // 局部变量数量(不包括参数) uint64_t localCount; // 局部变量数量(不包括参数)
uint64_t slotCount; // = 总参数数量 + 局部变量数量 uint64_t slotCount; // = 总参数数量 + 局部变量数量
}; };
}; }; // namespace Fig

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <cstdint> #include <cstdint>
#include <string_view> #include <string_view>
#define __FCORE_VERSION "0.4.4-alpha" #define __FCORE_VERSION "0.4.3-alpha"
#if defined(_WIN32) #if defined(_WIN32)
#define __FCORE_PLATFORM "Windows" #define __FCORE_PLATFORM "Windows"
@@ -54,6 +54,5 @@ namespace Fig
inline constexpr std::string_view COMPILER = __FCORE_COMPILER; inline constexpr std::string_view COMPILER = __FCORE_COMPILER;
inline constexpr std::string_view COMPILE_TIME = __FCORE_COMPILE_TIME; inline constexpr std::string_view COMPILE_TIME = __FCORE_COMPILE_TIME;
inline constexpr std::string_view ARCH = __FCORE_ARCH; inline constexpr std::string_view ARCH = __FCORE_ARCH;
inline constexpr FString MAIN_FUNCTION = u8"main";
}; // namespace Core }; // namespace Core
}; // namespace Fig }; // namespace Fig

View File

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

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Utils/magic_enum/magic_enum.hpp> #include <Utils/magic_enum/magic_enum.hpp>
#include <unordered_map> #include <unordered_map>
@@ -11,16 +11,17 @@ namespace Fig
{ {
private: private:
size_t id; // the id (standard) of warning size_t id; // the id (standard) of warning
FString msg; String msg;
size_t line, column; size_t line, column;
public: public:
static const std::unordered_map<size_t, FString> standardWarnings; static const std::unordered_map<size_t, String> standardWarnings;
Warning(size_t _id, FString _msg) Warning(size_t _id, String _msg)
{ {
id = _id; id = _id;
msg = std::move(_msg); 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; id = _id;
msg = std::move(_msg); msg = std::move(_msg);
@@ -28,28 +29,12 @@ namespace Fig
column = _column; column = _column;
} }
auto getIDName() auto getIDName() { return standardWarnings.at(id); }
{
return standardWarnings.at(id);
}
auto getID()
{
return id;
}
auto getMsg()
{
return msg;
}
auto getLine()
{
return line;
}
auto getColumn()
{
return column;
}
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 #pragma once
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <exception> #include <exception>
#include <format> #include <format>
@@ -14,20 +14,29 @@ namespace Fig
{ {
public: public:
explicit AddressableError() {} explicit AddressableError() {}
explicit AddressableError(FString _msg, explicit AddressableError(String _msg,
size_t _line, size_t _line,
size_t _column, size_t _column,
FString _sourcePath, String _sourcePath,
std::vector<FString> _sourceLines, std::vector<String> _sourceLines,
std::source_location loc = std::source_location::current()) : 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; 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()); std::string msg = std::format("[AddressableError] {} at {}:{}, in [{}] {}",
return FString(msg); 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 const char *what() const noexcept override
{ {
@@ -38,37 +47,36 @@ namespace Fig
virtual size_t getLine() const { return line; } virtual size_t getLine() const { return line; }
virtual size_t getColumn() const { return column; } virtual size_t getColumn() const { return column; }
FString getMessage() const { return message; } String getMessage() const { return message; }
FString getSourcePath() const { return sourcePath; } String getSourcePath() const { return sourcePath; }
std::vector<FString> getSourceLines() const { return sourceLines; } std::vector<String> getSourceLines() const { return sourceLines; }
virtual FString getErrorType() const virtual String getErrorType() const { return String(U"\1"); }
{
return FString(u8"AddressableError");
}
protected: protected:
size_t line, column; size_t line, column;
FString message; String message;
FString sourcePath; String sourcePath;
std::vector<FString> sourceLines; std::vector<String> sourceLines;
}; };
class UnaddressableError : public std::exception class UnaddressableError : public std::exception
{ {
public: public:
explicit UnaddressableError() {} explicit UnaddressableError() {}
explicit UnaddressableError(FString _msg, explicit UnaddressableError(String _msg, std::source_location loc = std::source_location::current()) :
std::source_location loc = std::source_location::current()) :
src_loc(loc) src_loc(loc)
{ {
message = _msg; 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()); std::string msg = std::format("[UnaddressableError] {} in [{}] {}",
return FString(msg); this->message.toBasicString(),
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
} }
const char *what() const noexcept override const char *what() const noexcept override
{ {
@@ -76,15 +84,12 @@ namespace Fig
return msg.c_str(); return msg.c_str();
} }
std::source_location src_loc; std::source_location src_loc;
FString getMessage() const { return message; } String getMessage() const { return message; }
virtual FString getErrorType() const virtual String getErrorType() const { return String(U"\1"); }
{
return FString(u8"UnaddressableError");
}
protected: protected:
FString message; String message;
}; };
class SyntaxError : public AddressableError class SyntaxError : public AddressableError
@@ -92,37 +97,36 @@ namespace Fig
public: public:
using AddressableError::AddressableError; 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()); std::string msg = std::format("[SyntaxError] {} in [{}] {}",
return FString(msg); this->message.toBasicString(),
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
} }
virtual FString getErrorType() const override virtual String getErrorType() const override { return String(U"\1"); }
{
return FString(u8"SyntaxError");
}
}; };
class RuntimeError final : public UnaddressableError class RuntimeError final : public UnaddressableError
{ {
public: public:
using UnaddressableError::UnaddressableError; using UnaddressableError::UnaddressableError;
explicit RuntimeError(FString _msg, explicit RuntimeError(String _msg, std::source_location loc = std::source_location::current()) :
std::source_location loc = std::source_location::current()) :
UnaddressableError(_msg, loc) 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()); std::string msg = std::format("[RuntimeError] {} in [{}] {}",
return FString(msg); this->message.toBasicString(),
this->src_loc.file_name(),
this->src_loc.function_name());
return String(msg);
} }
virtual FString getErrorType() const override virtual String getErrorType() const override { return String(U"\1"); }
{
return FString(u8"RuntimeError");
}
}; };
} // namespace Fig } // namespace Fig

View File

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

View File

@@ -13,7 +13,7 @@
#include <Evaluator/Value/interface.hpp> #include <Evaluator/Value/interface.hpp>
#include <Evaluator/Value/Type.hpp> #include <Evaluator/Value/Type.hpp>
#include <Evaluator/Context/context_forward.hpp> #include <Evaluator/Context/context_forward.hpp>
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Evaluator/Value/value.hpp> #include <Evaluator/Value/value.hpp>
#include <Evaluator/Value/VariableSlot.hpp> #include <Evaluator/Value/VariableSlot.hpp>
#include <Evaluator/Core/ExprResult.hpp> #include <Evaluator/Core/ExprResult.hpp>
@@ -26,7 +26,7 @@ namespace Fig
TypeInfo interfaceType; TypeInfo interfaceType;
TypeInfo structType; TypeInfo structType;
std::unordered_map<FString, Function> implMethods; std::unordered_map<String, Function> implMethods;
}; };
struct OperationRecord struct OperationRecord
@@ -49,11 +49,11 @@ namespace Fig
class Context : public std::enable_shared_from_this<Context> class Context : public std::enable_shared_from_this<Context>
{ {
private: private:
FString scopeName; String scopeName;
std::unordered_map<FString, std::shared_ptr<VariableSlot>> variables; std::unordered_map<String, std::shared_ptr<VariableSlot>> variables;
// std::unordered_map<std::size_t, Function> functions; // 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> // implRegistry <Struct, ordered list of ImplRecord>
std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash> implRegistry; std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash> implRegistry;
@@ -63,13 +63,13 @@ namespace Fig
ContextPtr parent; ContextPtr parent;
Context(const Context &) = default; 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 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) void merge(const Context &c)
{ {
@@ -80,13 +80,6 @@ namespace Fig
// c.structTypeNames.end()); // c.structTypeNames.end());
} }
void clear()
{
variables.clear();
implRegistry.clear();
opRegistry.clear();
}
std::unordered_map<size_t, Function> getFunctions() const std::unordered_map<size_t, Function> getFunctions() const
{ {
std::unordered_map<size_t, Function> result; std::unordered_map<size_t, Function> result;
@@ -101,58 +94,58 @@ namespace Fig
return result; return result;
} }
std::shared_ptr<VariableSlot> get(const FString &name) std::shared_ptr<VariableSlot> get(const String &name)
{ {
auto it = variables.find(name); auto it = variables.find(name);
if (it != variables.end()) return it->second; if (it != variables.end()) return it->second;
if (parent) return parent->get(name); 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; } if (variables.contains(name)) { return variables[name]->am; }
else if (parent != nullptr) { return parent->getAccessModifier(name); } else if (parent != nullptr) { return parent->getAccessModifier(name); }
else 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 AccessModifier am = getAccessModifier(name); // may throw
return !isAccessConst(am); return !isAccessConst(am);
} }
bool isVariablePublic(const FString &name) bool isVariablePublic(const String &name)
{ {
AccessModifier am = getAccessModifier(name); // may throw AccessModifier am = getAccessModifier(name); // may throw
return isAccessPublic(am); return isAccessPublic(am);
} }
void set(const FString &name, ObjectPtr value) void set(const String &name, ObjectPtr value)
{ {
if (variables.contains(name)) if (variables.contains(name))
{ {
if (!isVariableMutable(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; variables[name]->value = value;
} }
else if (parent != nullptr) { parent->set(name, value); } else if (parent != nullptr) { parent->set(name, value); }
else 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; } if (variables.contains(name)) { variables[name]->value = value; }
else if (parent != nullptr) { parent->_update(name, value); } else if (parent != nullptr) { parent->_update(name, value); }
else 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, const TypeInfo &ti,
AccessModifier am, AccessModifier am,
const ObjectPtr &value = Object::getNullInstance()) const ObjectPtr &value = Object::getNullInstance())
@@ -160,7 +153,7 @@ namespace Fig
if (containsInThisScope(name)) if (containsInThisScope(name))
{ {
throw RuntimeError( 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); variables[name] = std::make_shared<VariableSlot>(name, value, ti, am);
// if (ti == ValueType::StructType) // if (ti == ValueType::StructType)
@@ -170,17 +163,17 @@ namespace Fig
// } // }
} }
void 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)) if (containsInThisScope(name))
{ {
throw RuntimeError( 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); 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) for (auto &[name, slot] : variables)
{ {
@@ -192,7 +185,7 @@ namespace Fig
} }
return std::nullopt; return std::nullopt;
} }
// std::optional<FString> getStructName(std::size_t id) // std::optional<String> getStructName(std::size_t id)
// { // {
// auto it = structTypeNames.find(id); // auto it = structTypeNames.find(id);
// if (it != structTypeNames.end()) // if (it != structTypeNames.end())
@@ -208,21 +201,21 @@ namespace Fig
// return std::nullopt; // return std::nullopt;
// } // }
// } // }
bool contains(const FString &name) bool contains(const String &name)
{ {
if (variables.contains(name)) { return true; } if (variables.contains(name)) { return true; }
else if (parent != nullptr) { return parent->contains(name); } else if (parent != nullptr) { return parent->contains(name); }
return false; 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() bool isInFunctionContext()
{ {
ContextPtr ctx = shared_from_this(); ContextPtr ctx = shared_from_this();
while (ctx) while (ctx)
{ {
if (ctx->getScopeName().find(u8"<Function ") == 0) { return true; } if (ctx->getScopeName().find(U"\1") == 0) { return true; }
ctx = ctx->parent; ctx = ctx->parent;
} }
return false; return false;
@@ -232,10 +225,7 @@ namespace Fig
ContextPtr ctx = shared_from_this(); ContextPtr ctx = shared_from_this();
while (ctx) while (ctx)
{ {
if (ctx->getScopeName().find(u8"<While ") == 0 or ctx->getScopeName().find(u8"<For ") == 0) if (ctx->getScopeName().find(U"\1") == 0 or ctx->getScopeName().find(U"\1") == 0) { return true; }
{
return true;
}
ctx = ctx->parent; ctx = ctx->parent;
} }
return false; return false;
@@ -289,7 +279,7 @@ namespace Fig
list.push_back(record); // order is the level 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); auto it = implRegistry.find(structType);
if (it != implRegistry.end()) if (it != implRegistry.end())
@@ -303,7 +293,7 @@ namespace Fig
return parent && parent->hasMethodImplemented(structType, functionName); 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); auto it = implRegistry.find(structType);
if (it == implRegistry.end()) return false; if (it == implRegistry.end()) return false;
@@ -332,7 +322,7 @@ namespace Fig
return false; return false;
} }
Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const String &functionName)
{ {
// O(N²) // O(N²)
// SLOW // SLOW
@@ -373,7 +363,7 @@ namespace Fig
assert(false); 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); auto it = implRegistry.find(structType);
if (it != implRegistry.end()) if (it != implRegistry.end())

View File

@@ -12,7 +12,7 @@ namespace Fig
{ {
case AstType::ValueExpr: { case AstType::ValueExpr: {
auto val = std::static_pointer_cast<Ast::ValueExprAst>(exp); auto val = std::static_pointer_cast<Ast::ValueExprAst>(exp);
return val->val; return val->val;
} }
case AstType::VarExpr: { case AstType::VarExpr: {
@@ -22,17 +22,17 @@ namespace Fig
} }
case AstType::BinaryExpr: { case AstType::BinaryExpr: {
auto bin = std::static_pointer_cast<Ast::BinaryExprAst>(exp); auto bin = std::static_pointer_cast<Ast::BinaryExprAst>(exp);
return evalBinary(bin, ctx); return evalBinary(bin, ctx);
} }
case AstType::UnaryExpr: { case AstType::UnaryExpr: {
auto un = std::static_pointer_cast<Ast::UnaryExprAst>(exp); auto un = std::static_pointer_cast<Ast::UnaryExprAst>(exp);
return evalUnary(un, ctx); return evalUnary(un, ctx);
} }
case AstType::TernaryExpr: { case AstType::TernaryExpr: {
auto te = std::static_pointer_cast<Ast::TernaryExprAst>(exp); auto te = std::static_pointer_cast<Ast::TernaryExprAst>(exp);
return evalTernary(te, ctx); return evalTernary(te, ctx);
} }
case AstType::MemberExpr: case AstType::MemberExpr:
@@ -44,13 +44,11 @@ namespace Fig
} }
case AstType::FunctionLiteralExpr: { case AstType::FunctionLiteralExpr: {
auto fnLiteral = std::static_pointer_cast<Ast::FunctionLiteralExprAst>(exp); auto fnLiteral = std::static_pointer_cast<Ast::FunctionLiteralExprAst>(exp);
Ast::BlockStatement body = nullptr; Ast::BlockStatement body = nullptr;
if (fnLiteral->isExprMode()) if (fnLiteral->isExprMode())
{ {
Ast::Expression exprBody = fnLiteral->getExprBody(); Ast::Expression exprBody = fnLiteral->getExprBody();
const Ast::AstAddressInfo &aai = exprBody->getAAI(); const Ast::AstAddressInfo &aai = exprBody->getAAI();
Ast::Return st = std::make_shared<Ast::ReturnSt>(exprBody); Ast::Return st = std::make_shared<Ast::ReturnSt>(exprBody);
@@ -63,9 +61,8 @@ namespace Fig
else else
{ {
body = fnLiteral->getBlockBody(); 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 pass the ctx(fnLiteral eval context) as closure context
*/ */
@@ -74,13 +71,12 @@ namespace Fig
} }
case AstType::InitExpr: { case AstType::InitExpr: {
auto initExpr = std::static_pointer_cast<Ast::InitExprAst>(exp); auto initExpr = std::static_pointer_cast<Ast::InitExprAst>(exp);
return evalInitExpr(initExpr, ctx); return evalInitExpr(initExpr, ctx);
} }
case AstType::ListExpr: { case AstType::ListExpr: {
auto lstExpr = std::static_pointer_cast<Ast::ListExprAst>(exp); auto lstExpr = std::static_pointer_cast<Ast::ListExprAst>(exp);
List list; List list;
for (auto &exp : lstExpr->val) { list.push_back(check_unwrap(eval(exp, ctx))); } for (auto &exp : lstExpr->val) { list.push_back(check_unwrap(eval(exp, ctx))); }
@@ -89,19 +85,19 @@ namespace Fig
case AstType::MapExpr: { case AstType::MapExpr: {
auto mapExpr = std::static_pointer_cast<Ast::MapExprAst>(exp); auto mapExpr = std::static_pointer_cast<Ast::MapExprAst>(exp);
Map map; 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)); map[check_unwrap(eval(key, ctx))] = check_unwrap(eval(value, ctx));
} }
return std::make_shared<Object>(std::move(map)); return std::make_shared<Object>(std::move(map));
} }
default: { 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 return Object::getNullInstance(); // ignore warning
} }
}; }; // namespace Fig

View File

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

View File

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

View File

@@ -10,10 +10,10 @@ namespace Fig
{ {
LvObject structeLv = check_unwrap_lv(evalLv(initExpr->structe, ctx)); LvObject structeLv = check_unwrap_lv(evalLv(initExpr->structe, ctx));
ObjectPtr structTypeVal = structeLv.get(); ObjectPtr structTypeVal = structeLv.get();
const FString &structName = structeLv.name(); const String &structName = structeLv.name();
if (!structTypeVal->is<StructType>()) if (!structTypeVal->is<StructType>())
{ {
throw EvaluatorError(u8"NotAStructTypeError", throw EvaluatorError(U"NotAStructTypeError",
std::format("'{}' is not a structure type", structName.toBasicString()), std::format("'{}' is not a structure type", structName.toBasicString()),
initExpr); initExpr);
} }
@@ -27,7 +27,7 @@ namespace Fig
if (argSize > 1) if (argSize > 1)
{ {
throw EvaluatorError(u8"StructInitArgumentMismatchError", throw EvaluatorError(U"StructInitArgumentMismatchError",
std::format("Builtin class `{}` expects 0 or 1 argument, but {} were provided", std::format("Builtin class `{}` expects 0 or 1 argument, but {} were provided",
type.toString().toBasicString(), type.toString().toBasicString(),
argSize), argSize),
@@ -40,7 +40,7 @@ namespace Fig
if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function) if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"BuiltinNotConstructibleError", U"BuiltinNotConstructibleError",
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()), std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
initExpr); initExpr);
} }
@@ -50,7 +50,7 @@ namespace Fig
ObjectPtr val = check_unwrap(eval(args[0].second, ctx)); ObjectPtr val = check_unwrap(eval(args[0].second, ctx));
auto err = [&](const char *msg) { auto err = [&](const char *msg) {
throw EvaluatorError(u8"BuiltinInitTypeMismatchError", throw EvaluatorError(U"BuiltinInitTypeMismatchError",
std::format("Builtin `{}` constructor {}", type.toString().toBasicString(), msg), std::format("Builtin `{}` constructor {}", type.toString().toBasicString(), msg),
initExpr); initExpr);
}; };
@@ -121,7 +121,7 @@ namespace Fig
} }
throw EvaluatorError( throw EvaluatorError(
u8"BuiltinNotConstructibleError", U"BuiltinNotConstructibleError",
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()), std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
initExpr); initExpr);
} }
@@ -140,7 +140,7 @@ namespace Fig
size_t got = initExpr->args.size(); size_t got = initExpr->args.size();
if (got > maxArgs || got < minArgs) if (got > maxArgs || got < minArgs)
{ {
throw EvaluatorError(u8"StructInitArgumentMismatchError", throw EvaluatorError(U"StructInitArgumentMismatchError",
std::format("Structure '{}' expects {} to {} fields, but {} were provided", std::format("Structure '{}' expects {} to {} fields, but {} were provided",
structName.toBasicString(), structName.toBasicString(),
minArgs, minArgs,
@@ -149,9 +149,9 @@ namespace Fig
initExpr); 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) for (const auto &[argName, argExpr] : initExpr->args)
{ {
evaluatedArgs.push_back({argName, check_unwrap(eval(argExpr, ctx))}); evaluatedArgs.push_back({argName, check_unwrap(eval(argExpr, ctx))});
@@ -159,8 +159,8 @@ namespace Fig
return ExprResult::normal(Object::getNullInstance()); return ExprResult::normal(Object::getNullInstance());
}; };
ContextPtr instanceCtx = ContextPtr instanceCtx = std::make_shared<Context>(
std::make_shared<Context>(FString(std::format("<StructInstance {}>", structName.toBasicString())), defContext); String(std::format("<StructInstance {}>", structName.toBasicString())), defContext);
/* /*
3 ways of calling constructor 3 ways of calling constructor
.1 Person {"Fig", 1, "IDK"}; .1 Person {"Fig", 1, "IDK"};
@@ -176,22 +176,22 @@ namespace Fig
for (size_t i = 0; i < maxArgs; ++i) for (size_t i = 0; i < maxArgs; ++i)
{ {
const Field &field = structT.fields[i]; const Field &field = structT.fields[i];
const FString &fieldName = field.name; const String &fieldName = field.name;
const TypeInfo &expectedType = field.type; const TypeInfo &expectedType = field.type;
if (i >= evaluatedArgs.size()) if (i >= evaluatedArgs.size())
{ {
// we've checked argument count before, so here // we've checked argument count before, so here
// must be a default value // must be a default value
// evaluate default value in definition context! // evaluate default value in definition context
ObjectPtr defaultVal = check_unwrap(eval(field.defaultValue, ObjectPtr defaultVal = check_unwrap(eval(field.defaultValue,
defContext)); // it can't be null here ctx)); // it can't be null here
// type check // type check
if (!isTypeMatch(expectedType, defaultVal, ctx)) if (!isTypeMatch(expectedType, defaultVal, ctx))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"StructFieldTypeMismatchError", U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(), structName.toBasicString(),
fieldName.toBasicString(), fieldName.toBasicString(),
@@ -208,7 +208,7 @@ namespace Fig
if (!isTypeMatch(expectedType, argVal, ctx)) if (!isTypeMatch(expectedType, argVal, ctx))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"StructFieldTypeMismatchError", U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(), structName.toBasicString(),
fieldName.toBasicString(), fieldName.toBasicString(),
@@ -227,10 +227,10 @@ namespace Fig
for (size_t i = 0; i < maxArgs; ++i) for (size_t i = 0; i < maxArgs; ++i)
{ {
const Field &field = structT.fields[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)) if (instanceCtx->containsInThisScope(fieldName))
{ {
throw EvaluatorError(u8"StructFieldRedeclarationError", throw EvaluatorError(U"StructFieldRedeclarationError",
std::format("Field '{}' already initialized in structure '{}'", std::format("Field '{}' already initialized in structure '{}'",
fieldName.toBasicString(), fieldName.toBasicString(),
structName.toBasicString()), structName.toBasicString()),
@@ -248,7 +248,7 @@ namespace Fig
if (!isTypeMatch(expectedType, defaultVal, ctx)) if (!isTypeMatch(expectedType, defaultVal, ctx))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"StructFieldTypeMismatchError", U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(), structName.toBasicString(),
fieldName.toBasicString(), fieldName.toBasicString(),
@@ -264,7 +264,7 @@ namespace Fig
if (!isTypeMatch(field.type, argVal, ctx)) if (!isTypeMatch(field.type, argVal, ctx))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"StructFieldTypeMismatchError", U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(), structName.toBasicString(),
fieldName.toBasicString(), fieldName.toBasicString(),
@@ -291,7 +291,7 @@ namespace Fig
[&argName](const Field &f) { return f.name == argName; }); [&argName](const Field &f) { return f.name == argName; });
if (fieldIt == structT.fields.end()) if (fieldIt == structT.fields.end())
{ {
// throw EvaluatorError(u8"StructFieldNotFoundError", // throw EvaluatorError(U"StructFieldNotFoundError",
// std::format("Field '{}' not found in structure '{}'", // std::format("Field '{}' not found in structure '{}'",
// argName.toBasicString(), // argName.toBasicString(),
// structName.toBasicString()), // structName.toBasicString()),
@@ -303,7 +303,7 @@ namespace Fig
if (!isTypeMatch(field.type, argVal, ctx)) if (!isTypeMatch(field.type, argVal, ctx))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"StructFieldTypeMismatchError", U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(), structName.toBasicString(),
field.name.toBasicString(), field.name.toBasicString(),
@@ -332,7 +332,7 @@ namespace Fig
if (!isTypeMatch(field.type, defaultVal, ctx)) if (!isTypeMatch(field.type, defaultVal, ctx))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"StructFieldTypeMismatchError", U"StructFieldTypeMismatchError",
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
structName.toBasicString(), structName.toBasicString(),
field.name.toBasicString(), field.name.toBasicString(),
@@ -345,13 +345,14 @@ namespace Fig
} }
} }
} }
ContextPtr stDefCtx = structT.defContext;
// load struct method // load struct method
for (auto &[id, fn] : defContext->getFunctions()) for (auto &[id, fn] : stDefCtx->getFunctions())
{ {
const FString &funcName = fn.name; const String &funcName = fn.name;
const auto &funcSlot = defContext->get(funcName); const auto &funcSlot = stDefCtx->get(funcName);
instanceCtx->def(funcName, instanceCtx->def(funcName,
ValueType::Function, ValueType::Function,
funcSlot->am, funcSlot->am,
@@ -360,4 +361,4 @@ namespace Fig
return std::make_shared<Object>(StructInstance(structT.type, instanceCtx)); 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) ExprResult Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
{ {
const FString &name = var->name; const String &name = var->name;
// 调试信息 // 调试信息
// std::cerr << "=== DEBUG evalVarExpr ===" << std::endl; // std::cerr << "=== DEBUG evalVarExpr ===" << std::endl;
@@ -38,14 +38,14 @@ namespace Fig
// } // }
// end // 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); return LvObject(ctx->get(name), ctx);
} }
ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx) ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx)
{ {
// LvObject base = evalLv(me->base, ctx); // LvObject base = evalLv(me->base, ctx);
RvObject baseVal = check_unwrap(eval(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) if (baseVal->getTypeInfo() == ValueType::Module)
{ {
// std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl; // std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl;
@@ -74,7 +74,7 @@ namespace Fig
} }
else else
{ {
throw EvaluatorError(u8"VariableNotFoundError", throw EvaluatorError(U"VariableNotFoundError",
std::format("`{}` has not variable '{}', check if it is public", std::format("`{}` has not variable '{}', check if it is public",
baseVal->toString().toBasicString(), baseVal->toString().toBasicString(),
member.toBasicString()), member.toBasicString()),
@@ -118,7 +118,7 @@ namespace Fig
if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found
{ {
throw EvaluatorError( throw EvaluatorError(
u8"NoAttributeError", U"NoAttributeError",
std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()), std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()),
me->base); me->base);
} }
@@ -153,7 +153,7 @@ namespace Fig
} }
else else
{ {
throw EvaluatorError(u8"NoAttributeError", throw EvaluatorError(U"NoAttributeError",
std::format("`{}` has not attribute '{}' and no interfaces have been implemented it", std::format("`{}` has not attribute '{}' and no interfaces have been implemented it",
baseVal->toString().toBasicString(), baseVal->toString().toBasicString(),
member.toBasicString()), member.toBasicString()),
@@ -172,7 +172,7 @@ namespace Fig
if (index->getTypeInfo() != ValueType::Int) if (index->getTypeInfo() != ValueType::Int)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"TypeError", U"TypeError",
std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()), std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
ie->index); ie->index);
} }
@@ -181,7 +181,7 @@ namespace Fig
if (indexVal >= list.size()) if (indexVal >= list.size())
{ {
throw EvaluatorError( throw EvaluatorError(
u8"IndexOutOfRangeError", U"IndexOutOfRangeError",
std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()), std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()),
ie->index); ie->index);
} }
@@ -193,16 +193,16 @@ namespace Fig
if (index->getTypeInfo() != ValueType::Int) if (index->getTypeInfo() != ValueType::Int)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"TypeError", U"TypeError",
std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()), std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
ie->index); ie->index);
} }
FString &string = base->as<ValueType::StringClass>(); String &string = base->as<ValueType::StringClass>();
ValueType::IntClass indexVal = index->as<ValueType::IntClass>(); ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
if (indexVal >= string.length()) if (indexVal >= string.length())
{ {
throw EvaluatorError( throw EvaluatorError(
u8"IndexOutOfRangeError", U"IndexOutOfRangeError",
std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()), std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()),
ie->index); ie->index);
} }
@@ -211,7 +211,7 @@ namespace Fig
else else
{ {
throw EvaluatorError( throw EvaluatorError(
u8"NoSubscriptableError", U"NoSubscriptableError",
std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()), std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()),
ie->base); ie->base);
} }
@@ -239,7 +239,7 @@ namespace Fig
} }
default: { default: {
throw EvaluatorError( throw EvaluatorError(
u8"TypeError", U"TypeError",
std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()), std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
exp); exp);
} }

View File

@@ -1,10 +1,9 @@
#include <Ast/Statements/InterfaceDefSt.hpp>
#include <Evaluator/Core/ExprResult.hpp> #include <Evaluator/Core/ExprResult.hpp>
#include <Ast/AccessModifier.hpp> #include <Ast/AccessModifier.hpp>
#include <Ast/Expressions/FunctionCall.hpp> #include <Ast/Expressions/FunctionCall.hpp>
#include <Ast/astBase.hpp> #include <Ast/astBase.hpp>
#include <Ast/functionParameters.hpp> #include <Ast/functionParameters.hpp>
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Evaluator/Core/StatementResult.hpp> #include <Evaluator/Core/StatementResult.hpp>
#include <Evaluator/Value/Type.hpp> #include <Evaluator/Value/Type.hpp>
#include <Evaluator/Value/structType.hpp> #include <Evaluator/Value/structType.hpp>
@@ -15,7 +14,6 @@
#include <Utils/utils.hpp> #include <Utils/utils.hpp>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
namespace Fig namespace Fig
{ {
@@ -34,7 +32,7 @@ namespace Fig
if (ctx->containsInThisScope(varDef->name)) if (ctx->containsInThisScope(varDef->name))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"RedeclarationError", U"RedeclarationError",
std::format("Variable `{}` already declared in this scope", varDef->name.toBasicString()), std::format("Variable `{}` already declared in this scope", varDef->name.toBasicString()),
varDef); varDef);
} }
@@ -53,7 +51,7 @@ namespace Fig
if (value != nullptr && !isTypeMatch(declaredType, value, ctx)) if (value != nullptr && !isTypeMatch(declaredType, value, ctx))
{ {
throw EvaluatorError(u8"TypeError", throw EvaluatorError(U"TypeError",
std::format("Variable `{}` expects init-value type `{}`, but got '{}'", std::format("Variable `{}` expects init-value type `{}`, but got '{}'",
varDef->name.toBasicString(), varDef->name.toBasicString(),
prettyType(declaredTypeValue).toBasicString(), prettyType(declaredTypeValue).toBasicString(),
@@ -65,10 +63,6 @@ namespace Fig
value = std::make_shared<Object>(Object::defaultValue(declaredType)); value = std::make_shared<Object>(Object::defaultValue(declaredType));
} // else -> Ok } // else -> Ok
} // else -> type is Any (default) } // else -> type is Any (default)
else
{
value = Object::getNullInstance();
}
AccessModifier am = AccessModifier am =
(varDef->isConst ? (varDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const) : (varDef->isConst ? (varDef->isPublic ? AccessModifier::PublicConst : AccessModifier::Const) :
(varDef->isPublic ? AccessModifier::Public : AccessModifier::Normal)); (varDef->isPublic ? AccessModifier::Public : AccessModifier::Normal));
@@ -79,11 +73,11 @@ namespace Fig
case FunctionDefSt: { case FunctionDefSt: {
auto fnDef = std::static_pointer_cast<Ast::FunctionDefSt>(stmt); auto fnDef = std::static_pointer_cast<Ast::FunctionDefSt>(stmt);
const FString &fnName = fnDef->name; const String &fnName = fnDef->name;
if (ctx->containsInThisScope(fnName)) if (ctx->containsInThisScope(fnName))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"RedeclarationError", U"RedeclarationError",
std::format("Function `{}` already declared in this scope", fnName.toBasicString()), std::format("Function `{}` already declared in this scope", fnName.toBasicString()),
fnDef); fnDef);
} }
@@ -108,16 +102,16 @@ namespace Fig
if (ctx->containsInThisScope(stDef->name)) if (ctx->containsInThisScope(stDef->name))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"RedeclarationError", U"RedeclarationError",
std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()), std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()),
stDef); stDef);
} }
TypeInfo type(stDef->name, true); // register type name TypeInfo type(stDef->name, true); // register type name
ContextPtr defContext = std::make_shared<Context>(FString(std::format("<Struct {} at {}:{}>", ContextPtr defContext = std::make_shared<Context>(String(std::format("<Struct {} at {}:{}>",
stDef->name.toBasicString(), stDef->name.toBasicString(),
stDef->getAAI().line, stDef->getAAI().line,
stDef->getAAI().column)), stDef->getAAI().column)),
ctx); ctx);
ObjectPtr structTypeObj = std::make_shared<Object>(StructType(type, defContext, {})); ObjectPtr structTypeObj = std::make_shared<Object>(StructType(type, defContext, {}));
@@ -130,12 +124,12 @@ namespace Fig
structTypeObj); // predef to itself, always const structTypeObj); // predef to itself, always const
std::vector<Field> fields; std::vector<Field> fields;
std::vector<FString> _fieldNames; std::vector<String> _fieldNames;
for (Ast::StructDefField field : stDef->fields) for (Ast::StructDefField field : stDef->fields)
{ {
if (Utils::vectorContains(field.fieldName, _fieldNames)) if (Utils::vectorContains(field.fieldName, _fieldNames))
{ {
throw EvaluatorError(u8"RedeclarationError", throw EvaluatorError(U"RedeclarationError",
std::format("Field '{}' already defined in structure '{}'", std::format("Field '{}' already defined in structure '{}'",
field.fieldName.toBasicString(), field.fieldName.toBasicString(),
stDef->name.toBasicString()), stDef->name.toBasicString()),
@@ -157,7 +151,7 @@ namespace Fig
{ {
if (st->getType() != Ast::AstType::FunctionDefSt) if (st->getType() != Ast::AstType::FunctionDefSt)
{ {
throw EvaluatorError(u8"UnexpectedStatementInStructError", throw EvaluatorError(U"UnexpectedStatementInStructError",
std::format("Unexpected statement `{}` in struct declaration", std::format("Unexpected statement `{}` in struct declaration",
st->toString().toBasicString()), st->toString().toBasicString()),
st); st);
@@ -170,56 +164,20 @@ namespace Fig
case InterfaceDefSt: { case InterfaceDefSt: {
auto ifd = std::static_pointer_cast<Ast::InterfaceDefAst>(stmt); auto ifd = std::static_pointer_cast<Ast::InterfaceDefAst>(stmt);
const FString &interfaceName = ifd->name; const String &interfaceName = ifd->name;
const std::vector<Ast::Expression> &bundle_exprs = ifd->bundles;
if (ctx->containsInThisScope(interfaceName)) if (ctx->containsInThisScope(interfaceName))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"RedeclarationError", U"RedeclarationError",
std::format("Interface `{}` already declared in this scope", interfaceName.toBasicString()), std::format("Interface `{}` already declared in this scope", interfaceName.toBasicString()),
ifd); ifd);
} }
std::vector<Ast::InterfaceMethod> bundle_methods;
std::unordered_map<FString, FString> cache_methods;
// K: interface method name V: method owner (interface)
for (const auto &exp : bundle_exprs)
{
ObjectPtr itf_val = check_unwrap_stres(eval(exp, ctx));
if (!itf_val->is<InterfaceType>())
{
throw EvaluatorError(u8"TypeError",
std::format("Cannot bundle type '{}' that is not interface",
prettyType(itf_val).toBasicString()),
exp);
}
const InterfaceType &itfType = itf_val->as<InterfaceType>();
for (const auto &method : itfType.methods)
{
if (cache_methods.contains(method.name))
{
throw EvaluatorError(u8"DuplicateInterfaceMethodError",
std::format("Interface `{}` has duplicate method '{}' with '{}.{}'",
itfType.type.toString().toBasicString(),
method.name.toBasicString(),
cache_methods[method.name].toBasicString(),
method.name.toBasicString()),
ifd);
}
cache_methods[method.name] = itfType.type.toString();
bundle_methods.push_back(method);
}
}
std::vector<Ast::InterfaceMethod> methods(ifd->methods);
methods.insert(methods.end(), bundle_methods.begin(), bundle_methods.end());
TypeInfo type(interfaceName, true); // register interface TypeInfo type(interfaceName, true); // register interface
ctx->def(interfaceName, ctx->def(interfaceName,
type, type,
(ifd->isPublic ? AccessModifier::PublicConst : AccessModifier::Const), (ifd->isPublic ? AccessModifier::PublicConst : AccessModifier::Const),
std::make_shared<Object>(InterfaceType(type, methods))); std::make_shared<Object>(InterfaceType(type, ifd->methods)));
return StatementResult::normal(); return StatementResult::normal();
} }
@@ -230,7 +188,7 @@ namespace Fig
TypeInfo interfaceType(ip->interfaceName); TypeInfo interfaceType(ip->interfaceName);
if (ctx->hasImplRegisted(structType, interfaceType)) if (ctx->hasImplRegisted(structType, interfaceType))
{ {
throw EvaluatorError(u8"DuplicateImplError", throw EvaluatorError(U"DuplicateImplError",
std::format("Duplicate implement `{}` for `{}`", std::format("Duplicate implement `{}` for `{}`",
interfaceType.toString().toBasicString(), interfaceType.toString().toBasicString(),
structType.toString().toBasicString()), structType.toString().toBasicString()),
@@ -238,13 +196,13 @@ namespace Fig
} }
if (!ctx->contains(ip->interfaceName)) if (!ctx->contains(ip->interfaceName))
{ {
throw EvaluatorError(u8"InterfaceNotFoundError", throw EvaluatorError(U"InterfaceNotFoundError",
std::format("Interface '{}' not found", ip->interfaceName.toBasicString()), std::format("Interface '{}' not found", ip->interfaceName.toBasicString()),
ip); ip);
} }
if (!ctx->contains(ip->structName)) if (!ctx->contains(ip->structName))
{ {
throw EvaluatorError(u8"StructNotFoundError", throw EvaluatorError(U"StructNotFoundError",
std::format("Struct '{}' not found", ip->structName.toBasicString()), std::format("Struct '{}' not found", ip->structName.toBasicString()),
ip); ip);
} }
@@ -260,21 +218,21 @@ namespace Fig
if (!interfaceObj->is<InterfaceType>()) if (!interfaceObj->is<InterfaceType>())
{ {
throw EvaluatorError( throw EvaluatorError(
u8"NotAInterfaceError", U"NotAInterfaceError",
std::format("Variable `{}` is not a interface", ip->interfaceName.toBasicString()), std::format("Variable `{}` is not a interface", ip->interfaceName.toBasicString()),
ip); ip);
} }
if (!structTypeObj->is<StructType>()) if (!structTypeObj->is<StructType>())
{ {
throw EvaluatorError( throw EvaluatorError(
u8"NotAStructType", U"NotAStructType",
std::format("Variable `{}` is not a struct type", ip->structName.toBasicString()), std::format("Variable `{}` is not a struct type", ip->structName.toBasicString()),
ip); ip);
} }
auto &implementMethods = ip->methods; auto &implementMethods = ip->methods;
if (ip->interfaceName == u8"Operation") if (ip->interfaceName == U"Operation")
{ {
// 运算符重载 // 运算符重载
/* /*
@@ -285,52 +243,52 @@ namespace Fig
*/ */
if (ValueType::isTypeBuiltin(structType)) if (ValueType::isTypeBuiltin(structType))
{ {
throw EvaluatorError(u8"BadUserError", throw EvaluatorError(U"BadUserError",
std::format("Don't overload built-in type operators plz! `{}`", std::format("Don't overload built-in type operators plz! `{}`",
prettyType(structTypeObj).toBasicString()), prettyType(structTypeObj).toBasicString()),
ip); ip);
} }
using enum Ast::Operator; 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}}, {U"Add", {Ast::Operator::Add, 2}},
{u8"Sub", {Ast::Operator::Subtract, 2}}, {U"Sub", {Ast::Operator::Subtract, 2}},
{u8"Mul", {Ast::Operator::Multiply, 2}}, {U"Mul", {Ast::Operator::Multiply, 2}},
{u8"Div", {Ast::Operator::Divide, 2}}, {U"Div", {Ast::Operator::Divide, 2}},
{u8"Mod", {Ast::Operator::Modulo, 2}}, {U"Mod", {Ast::Operator::Modulo, 2}},
{u8"Pow", {Ast::Operator::Power, 2}}, {U"Pow", {Ast::Operator::Power, 2}},
// 逻辑(一元) // 逻辑(一元)
{u8"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号 {U"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号
{u8"Not", {Ast::Operator::Not, 1}}, {U"Not", {Ast::Operator::Not, 1}},
// 逻辑(二元) // 逻辑(二元)
{u8"And", {Ast::Operator::And, 2}}, {U"And", {Ast::Operator::And, 2}},
{u8"Or", {Ast::Operator::Or, 2}}, {U"Or", {Ast::Operator::Or, 2}},
// 比较 // 比较
{u8"Equal", {Ast::Operator::Equal, 2}}, {U"Equal", {Ast::Operator::Equal, 2}},
{u8"NotEqual", {Ast::Operator::NotEqual, 2}}, {U"NotEqual", {Ast::Operator::NotEqual, 2}},
{u8"LessThan", {Ast::Operator::Less, 2}}, {U"LessThan", {Ast::Operator::Less, 2}},
{u8"LessEqual", {Ast::Operator::LessEqual, 2}}, {U"LessEqual", {Ast::Operator::LessEqual, 2}},
{u8"GreaterThan", {Ast::Operator::Greater, 2}}, {U"GreaterThan", {Ast::Operator::Greater, 2}},
{u8"GreaterEqual", {Ast::Operator::GreaterEqual, 2}}, {U"GreaterEqual", {Ast::Operator::GreaterEqual, 2}},
{u8"Is", {Ast::Operator::Is, 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}}, {U"BitAnd", {Ast::Operator::BitAnd, 2}},
{u8"BitOr", {Ast::Operator::BitOr, 2}}, {U"BitOr", {Ast::Operator::BitOr, 2}},
{u8"BitXor", {Ast::Operator::BitXor, 2}}, {U"BitXor", {Ast::Operator::BitXor, 2}},
{u8"ShiftLeft", {Ast::Operator::ShiftLeft, 2}}, {U"ShiftLeft", {Ast::Operator::ShiftLeft, 2}},
{u8"ShiftRight", {Ast::Operator::ShiftRight, 2}}, {U"ShiftRight", {Ast::Operator::ShiftRight, 2}},
}; };
for (auto &implMethod : implementMethods) for (auto &implMethod : implementMethods)
{ {
const FString &opName = implMethod.name; const String &opName = implMethod.name;
if (!magic_name_to_op.contains(opName)) if (!magic_name_to_op.contains(opName))
{ {
// ... 现在忽略 // ... 现在忽略
@@ -345,7 +303,7 @@ namespace Fig
if (ctx->hasOperatorImplemented(structType, op, (expectArgCnt == 1 ? true : false))) if (ctx->hasOperatorImplemented(structType, op, (expectArgCnt == 1 ? true : false)))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"DuplicateImplementError", U"DuplicateImplementError",
std::format("{} has already implement by another interface", opName.toBasicString()), std::format("{} has already implement by another interface", opName.toBasicString()),
ip); ip);
} }
@@ -354,7 +312,7 @@ namespace Fig
if (paraCnt != expectArgCnt || implMethod.paras.size() != expectArgCnt) if (paraCnt != expectArgCnt || implMethod.paras.size() != expectArgCnt)
{ {
// 特化报错,更详细易读 // 特化报错,更详细易读
throw EvaluatorError(u8"InterfaceSignatureMismatch", throw EvaluatorError(U"InterfaceSignatureMismatch",
std::format("Operator {} for {} arg count must be {}, got {}", std::format("Operator {} for {} arg count must be {}, got {}",
opName.toBasicString(), opName.toBasicString(),
structLv.name().toBasicString(), structLv.name().toBasicString(),
@@ -363,13 +321,13 @@ namespace Fig
ip); ip);
} }
FString opFnName(u8"Operation." + prettyType(structTypeObj) + u8"." + opName); String opFnName(U"Operation." + prettyType(structTypeObj) + U"." + opName);
ContextPtr fnCtx = std::make_shared<Context>( 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 auto &fillOpFnParas = [this, structType, implMethod, opFnName, fnCtx, ctx, paraCnt](
const std::vector<ObjectPtr> &args) -> StatementResult { const std::vector<ObjectPtr> &args) {
const Ast::FunctionParameters &paras = implMethod.paras; const Ast::FunctionParameters &paras = implMethod.paras;
for (size_t i = 0; i < paraCnt; ++i) for (size_t i = 0; i < paraCnt; ++i)
{ {
@@ -378,7 +336,7 @@ namespace Fig
if (paraType != ValueType::Any && paraType != structType) if (paraType != ValueType::Any && paraType != structType)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"ParameterTypeError", U"ParameterTypeError",
std::format("Invalid op fn parameter type '{}' of `{}`, must be `{}`", std::format("Invalid op fn parameter type '{}' of `{}`, must be `{}`",
paraType.toString().toBasicString(), paraType.toString().toBasicString(),
paras.posParas[i].first.toBasicString(), paras.posParas[i].first.toBasicString(),
@@ -387,7 +345,6 @@ namespace Fig
} }
fnCtx->def(paras.posParas[i].first, paraType, AccessModifier::Normal, args[i]); fnCtx->def(paras.posParas[i].first, paraType, AccessModifier::Normal, args[i]);
} }
return StatementResult::normal();
}; };
if (paraCnt == 1) if (paraCnt == 1)
@@ -428,12 +385,12 @@ namespace Fig
// ===== interface implementation validation ===== // ===== interface implementation validation =====
ImplRecord record{interfaceType, structType, {}}; ImplRecord record{interfaceType, structType, {}};
std::unordered_map<FString, Ast::InterfaceMethod> ifaceMethods; std::unordered_map<String, Ast::InterfaceMethod> ifaceMethods;
for (auto &m : interface.methods) for (auto &m : interface.methods)
{ {
if (ifaceMethods.contains(m.name)) if (ifaceMethods.contains(m.name))
{ {
throw EvaluatorError(u8"InterfaceDuplicateMethodError", throw EvaluatorError(U"InterfaceDuplicateMethodError",
std::format("Interface '{}' has duplicate method '{}'", std::format("Interface '{}' has duplicate method '{}'",
interfaceType.toString().toBasicString(), interfaceType.toString().toBasicString(),
m.name.toBasicString()), m.name.toBasicString()),
@@ -442,16 +399,16 @@ namespace Fig
ifaceMethods[m.name] = m; ifaceMethods[m.name] = m;
} }
std::unordered_set<FString> implemented; std::unordered_set<String> implemented;
for (auto &implMethod : implementMethods) for (auto &implMethod : implementMethods)
{ {
const FString &name = implMethod.name; const String &name = implMethod.name;
// ---- redundant impl ---- // ---- redundant impl ----
if (!ifaceMethods.contains(name)) if (!ifaceMethods.contains(name))
{ {
throw EvaluatorError(u8"RedundantImplementationError", throw EvaluatorError(U"RedundantImplementationError",
std::format("Struct '{}' implements extra method '{}' " std::format("Struct '{}' implements extra method '{}' "
"which is not required by interface '{}'", "which is not required by interface '{}'",
structType.toString().toBasicString(), structType.toString().toBasicString(),
@@ -462,7 +419,7 @@ namespace Fig
if (implemented.contains(name)) if (implemented.contains(name))
{ {
throw EvaluatorError(u8"DuplicateImplementMethodError", throw EvaluatorError(U"DuplicateImplementMethodError",
std::format("Duplicate implement method '{}'", name.toBasicString()), std::format("Duplicate implement method '{}'", name.toBasicString()),
ip); ip);
} }
@@ -472,7 +429,7 @@ namespace Fig
// ---- signature check ---- // ---- signature check ----
if (!isInterfaceSignatureMatch(implMethod, ifMethod)) if (!isInterfaceSignatureMatch(implMethod, ifMethod))
{ {
throw EvaluatorError(u8"InterfaceSignatureMismatch", throw EvaluatorError(U"InterfaceSignatureMismatch",
std::format("Interface method '{}({})' signature mismatch with " std::format("Interface method '{}({})' signature mismatch with "
"implementation '{}({})'", "implementation '{}({})'",
ifMethod.name.toBasicString(), ifMethod.name.toBasicString(),
@@ -484,7 +441,7 @@ namespace Fig
if (ctx->hasMethodImplemented(structType, name)) if (ctx->hasMethodImplemented(structType, name))
{ {
throw EvaluatorError(u8"DuplicateImplementMethodError", throw EvaluatorError(U"DuplicateImplementMethodError",
std::format("Method '{}' already implemented by another interface " std::format("Method '{}' already implemented by another interface "
"for struct '{}'", "for struct '{}'",
name.toBasicString(), name.toBasicString(),
@@ -506,7 +463,7 @@ namespace Fig
if (m.hasDefaultBody()) continue; if (m.hasDefaultBody()) continue;
throw EvaluatorError(u8"MissingImplementationError", throw EvaluatorError(U"MissingImplementationError",
std::format("Struct '{}' does not implement required interface method '{}' " std::format("Struct '{}' does not implement required interface method '{}' "
"and interface '{}' provides no default implementation", "and interface '{}' provides no default implementation",
structType.toString().toBasicString(), structType.toString().toBasicString(),
@@ -525,7 +482,7 @@ namespace Fig
if (condVal->getTypeInfo() != ValueType::Bool) if (condVal->getTypeInfo() != ValueType::Bool)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"TypeError", U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
ifSt->condition); ifSt->condition);
} }
@@ -537,7 +494,7 @@ namespace Fig
if (elifCondVal->getTypeInfo() != ValueType::Bool) if (elifCondVal->getTypeInfo() != ValueType::Bool)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"TypeError", U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
ifSt->condition); ifSt->condition);
} }
@@ -554,13 +511,13 @@ namespace Fig
if (condVal->getTypeInfo() != ValueType::Bool) if (condVal->getTypeInfo() != ValueType::Bool)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"TypeError", U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
whileSt->condition); whileSt->condition);
} }
if (!condVal->as<ValueType::BoolClass>()) { break; } if (!condVal->as<ValueType::BoolClass>()) { break; }
ContextPtr loopContext = std::make_shared<Context>( 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 ctx); // every loop has its own context
StatementResult sr = evalBlockStatement(whileSt->body, loopContext); StatementResult sr = evalBlockStatement(whileSt->body, loopContext);
if (sr.shouldReturn()) { return sr; } if (sr.shouldReturn()) { return sr; }
@@ -572,18 +529,13 @@ namespace Fig
case ForSt: { case ForSt: {
auto forSt = std::static_pointer_cast<Ast::ForSt>(stmt); auto forSt = std::static_pointer_cast<Ast::ForSt>(stmt);
ContextPtr loopContext = std::make_shared<Context>( 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 ctx); // for loop has its own context
evalStatement(forSt->initSt, evalStatement(forSt->initSt,
loopContext); // ignore init statement result loopContext); // ignore init statement result
size_t iteration = 0; size_t iteration = 0;
ContextPtr iterationContext = std::make_shared<Context>(
FString(std::format(
"<For {}:{}, Iteration {}>", forSt->getAAI().line, forSt->getAAI().column, iteration)),
loopContext); // every loop has its own context
while (true) // use while loop to simulate for loop, cause we while (true) // use while loop to simulate for loop, cause we
// need to check condition type every iteration // need to check condition type every iteration
{ {
@@ -591,18 +543,17 @@ namespace Fig
if (condVal->getTypeInfo() != ValueType::Bool) if (condVal->getTypeInfo() != ValueType::Bool)
{ {
throw EvaluatorError( throw EvaluatorError(
u8"TypeError", U"TypeError",
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
forSt->condition); forSt->condition);
} }
if (!condVal->as<ValueType::BoolClass>()) { break; } if (!condVal->as<ValueType::BoolClass>()) { break; }
iteration++; iteration++;
ContextPtr iterationContext = std::make_shared<Context>(
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); StatementResult sr = evalBlockStatement(forSt->body, iterationContext);
iterationContext->clear();
iterationContext->setScopeName(FString(std::format(
"<For {}:{}, Iteration {}>", forSt->getAAI().line, forSt->getAAI().column, iteration)));
if (sr.shouldReturn()) { return sr; } if (sr.shouldReturn()) { return sr; }
if (sr.shouldBreak()) { break; } if (sr.shouldBreak()) { break; }
if (sr.shouldContinue()) if (sr.shouldContinue())
@@ -620,7 +571,7 @@ namespace Fig
auto tryst = std::static_pointer_cast<Ast::TrySt>(stmt); auto tryst = std::static_pointer_cast<Ast::TrySt>(stmt);
ContextPtr tryCtx = std::make_shared<Context>( 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(); StatementResult sr = StatementResult::normal();
bool crashed = false; bool crashed = false;
for (auto &stmt : tryst->body->stmts) for (auto &stmt : tryst->body->stmts)
@@ -635,13 +586,12 @@ namespace Fig
bool catched = false; bool catched = false;
for (auto &cat : tryst->catches) for (auto &cat : tryst->catches)
{ {
const FString &errVarName = cat.errVarName; const String &errVarName = cat.errVarName;
TypeInfo errVarType = (cat.hasType ? TypeInfo(cat.errVarType) : ValueType::Any); TypeInfo errVarType = (cat.hasType ? TypeInfo(cat.errVarType) : ValueType::Any);
if (isTypeMatch(errVarType, sr.result, ctx)) if (isTypeMatch(errVarType, sr.result, ctx))
{ {
ContextPtr catchCtx = std::make_shared<Context>( ContextPtr catchCtx = std::make_shared<Context>(
FString( String(std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
ctx); ctx);
catchCtx->def(errVarName, errVarType, AccessModifier::Normal, sr.result); catchCtx->def(errVarName, errVarType, AccessModifier::Normal, sr.result);
sr = evalBlockStatement(cat.body, catchCtx); sr = evalBlockStatement(cat.body, catchCtx);
@@ -651,7 +601,7 @@ namespace Fig
} }
if (!catched && crashed) if (!catched && crashed)
{ {
throw EvaluatorError(u8"UncaughtExceptionError", throw EvaluatorError(U"UncaughtExceptionError",
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
tryst); tryst);
} }
@@ -665,7 +615,7 @@ namespace Fig
ObjectPtr value = check_unwrap_stres(eval(ts->value, ctx)); ObjectPtr value = check_unwrap_stres(eval(ts->value, ctx));
if (value->is<ValueType::NullClass>()) 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); return StatementResult::errorFlow(value);
} }
@@ -681,11 +631,11 @@ namespace Fig
case BreakSt: { case BreakSt: {
if (!ctx->parent) 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()) 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(); return StatementResult::breakFlow();
} }
@@ -693,11 +643,11 @@ namespace Fig
case ContinueSt: { case ContinueSt: {
if (!ctx->parent) 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()) 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(); return StatementResult::continueFlow();
} }
@@ -711,13 +661,13 @@ namespace Fig
auto block = std::static_pointer_cast<Ast::BlockStatementAst>(stmt); auto block = std::static_pointer_cast<Ast::BlockStatementAst>(stmt);
ContextPtr blockCtx = std::make_shared<Context>( 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); return evalBlockStatement(block, blockCtx);
} }
default: default:
throw RuntimeError( 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 }; // namespace Fig

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Evaluator/Value/function.hpp> #include <Evaluator/Value/function.hpp>
#include <Evaluator/Value/interface.hpp> #include <Evaluator/Value/interface.hpp>
#include <Evaluator/Value/structType.hpp> #include <Evaluator/Value/structType.hpp>
@@ -43,7 +43,7 @@ namespace Fig
} }
TypeInfo actualType(std::shared_ptr<const Object> obj); 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 &); bool operator==(const Object &, const Object &);
@@ -93,89 +93,92 @@ namespace Fig
Module, Module,
InterfaceType>; InterfaceType>;
static std::unordered_map<TypeInfo, std::unordered_map<FString, BuiltinTypeMemberFn>, TypeInfoHash> static std::unordered_map<TypeInfo, std::unordered_map<String, BuiltinTypeMemberFn>, TypeInfoHash>
getMemberTypeFunctions() 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{ memberTypeFunctions{
{ValueType::Null, {}}, {ValueType::Null, {}},
{ValueType::Int, {}}, {ValueType::Int, {}},
{ValueType::Double, {}}, {ValueType::Double, {}},
{ValueType::String, {ValueType::String,
{ {
{u8"length", {U"length",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 0) if (args.size() != 0)
throw RuntimeError( throw RuntimeError(
FString(std::format("`length` expects 0 arguments, {} got", args.size()))); String(std::format("`length` expects 0 arguments, {} got", args.size())));
const FString &str = object->as<ValueType::StringClass>(); const String &str = object->as<ValueType::StringClass>();
return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length())); return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length()));
}}, }},
{u8"replace", {U"replace",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2) if (args.size() != 2)
throw RuntimeError( throw RuntimeError(
FString(std::format("`replace` expects 2 arguments, {} got", args.size()))); String(std::format("`replace` expects 2 arguments, {} got", args.size())));
FString &str = object->as<ValueType::StringClass>(); String &str = object->as<ValueType::StringClass>();
ObjectPtr arg1 = args[0]; ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1]; ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>()) 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>()) 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(); return Object::getNullInstance();
}}, }},
{u8"erase", {U"erase",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2) if (args.size() != 2)
throw RuntimeError( throw RuntimeError(
FString(std::format("`erase` expects 2 arguments, {} got", args.size()))); String(std::format("`erase` expects 2 arguments, {} got", args.size())));
FString &str = object->as<ValueType::StringClass>(); String &str = object->as<ValueType::StringClass>();
ObjectPtr arg1 = args[0]; ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1]; ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>()) 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>()) 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 index = arg1->as<ValueType::IntClass>();
ValueType::IntClass n = arg2->as<ValueType::IntClass>(); ValueType::IntClass n = arg2->as<ValueType::IntClass>();
if (index < 0 || n < 0) 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()) 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(); return Object::getNullInstance();
}}, }},
{u8"insert", {U"insert",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2) if (args.size() != 2)
throw RuntimeError( throw RuntimeError(
FString(std::format("`insert` expects 2 arguments, {} got", args.size()))); String(std::format("`insert` expects 2 arguments, {} got", args.size())));
FString &str = object->as<ValueType::StringClass>(); String &str = object->as<ValueType::StringClass>();
ObjectPtr arg1 = args[0]; ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1]; ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>()) 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>()) 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(); return Object::getNullInstance();
}}, }},
}}, }},
@@ -184,34 +187,34 @@ namespace Fig
{ValueType::StructInstance, {}}, {ValueType::StructInstance, {}},
{ValueType::List, {ValueType::List,
{ {
{u8"length", {U"length",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 0) if (args.size() != 0)
throw RuntimeError( 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>(); const List &list = object->as<List>();
return std::make_shared<Object>(static_cast<ValueType::IntClass>(list.size())); return std::make_shared<Object>(static_cast<ValueType::IntClass>(list.size()));
}}, }},
{u8"get", {U"get",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1) if (args.size() != 1)
throw RuntimeError( 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]; ObjectPtr arg = args[0];
if (arg->getTypeInfo() != ValueType::Int) if (arg->getTypeInfo() != ValueType::Int)
throw RuntimeError( throw RuntimeError(
FString(std::format("`get` argument 1 expects Int, {} got", String(std::format("`get` argument 1 expects Int, {} got",
arg->getTypeInfo().toString().toBasicString()))); arg->getTypeInfo().toString().toBasicString())));
ValueType::IntClass i = arg->as<ValueType::IntClass>(); ValueType::IntClass i = arg->as<ValueType::IntClass>();
const List &list = object->as<List>(); const List &list = object->as<List>();
if (i >= list.size()) return Object::getNullInstance(); if (i >= list.size()) return Object::getNullInstance();
return list[i].value; return list[i].value;
}}, }},
{u8"push", {U"push",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1) if (args.size() != 1)
throw RuntimeError( 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]; ObjectPtr arg = args[0];
List &list = object->as<List>(); List &list = object->as<List>();
list.push_back(arg); list.push_back(arg);
@@ -220,21 +223,21 @@ namespace Fig
}}, }},
{ValueType::Map, {ValueType::Map,
{ {
{u8"get", {U"get",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1) if (args.size() != 1)
throw RuntimeError( 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]; ObjectPtr index = args[0];
const Map &map = object->as<Map>(); const Map &map = object->as<Map>();
if (!map.contains(index)) return Object::getNullInstance(); if (!map.contains(index)) return Object::getNullInstance();
return map.at(index); return map.at(index);
}}, }},
{u8"contains", {U"contains",
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr { [](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 1) if (args.size() != 1)
throw RuntimeError( 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]; ObjectPtr index = args[0];
const Map &map = object->as<Map>(); const Map &map = object->as<Map>();
return std::make_shared<Object>(map.contains(index)); return std::make_shared<Object>(map.contains(index));
@@ -246,29 +249,28 @@ namespace Fig
return memberTypeFunctions; return memberTypeFunctions;
} }
static std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash> static std::unordered_map<TypeInfo, std::unordered_map<String, int>, TypeInfoHash> getMemberTypeFunctionsParas()
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{ memberTypeFunctionsParas{
{ValueType::Null, {}}, {ValueType::Null, {}},
{ValueType::Int, {}}, {ValueType::Int, {}},
{ValueType::Double, {}}, {ValueType::Double, {}},
{ValueType::String, {ValueType::String,
{ {
{u8"length", 0}, {U"length", 0},
{u8"replace", 2}, {U"replace", 2},
{u8"erase", 2}, {U"erase", 2},
{u8"insert", 2}, {U"insert", 2},
}}, }},
{ValueType::Function, {}}, {ValueType::Function, {}},
{ValueType::StructType, {}}, {ValueType::StructType, {}},
{ValueType::StructInstance, {}}, {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, {ValueType::Map,
{ {
{u8"get", 1}, {U"get", 1},
{u8"contains", 1}, {U"contains", 1},
}}, }},
{ValueType::Module, {}}, {ValueType::Module, {}},
{ValueType::InterfaceType, {}}, {ValueType::InterfaceType, {}},
@@ -276,15 +278,15 @@ namespace Fig
return memberTypeFunctionsParas; return memberTypeFunctionsParas;
} }
bool hasMemberFunction(const FString &name) const bool hasMemberFunction(const String &name) const
{ {
return getMemberTypeFunctions().at(getTypeInfo()).contains(name); return getMemberTypeFunctions().at(getTypeInfo()).contains(name);
} }
BuiltinTypeMemberFn getMemberFunction(const FString &name) const BuiltinTypeMemberFn getMemberFunction(const String &name) const
{ {
return getMemberTypeFunctions().at(getTypeInfo()).at(name); return getMemberTypeFunctions().at(getTypeInfo()).at(name);
} }
int getMemberFunctionParaCount(const FString &name) const int getMemberFunctionParaCount(const String &name) const
{ {
return getMemberTypeFunctionsParas().at(getTypeInfo()).at(name); return getMemberTypeFunctionsParas().at(getTypeInfo()).at(name);
} }
@@ -317,7 +319,7 @@ namespace Fig
else if (ti == ValueType::Double) else if (ti == ValueType::Double)
return Object(ValueType::DoubleClass(0.0)); return Object(ValueType::DoubleClass(0.0));
else if (ti == ValueType::String) else if (ti == ValueType::String)
return Object(ValueType::StringClass(u8"")); return Object(ValueType::StringClass(U""));
else if (ti == ValueType::Bool) else if (ti == ValueType::Bool)
return Object(ValueType::BoolClass(false)); return Object(ValueType::BoolClass(false));
else if (ti == ValueType::List) else if (ti == ValueType::List)
@@ -420,85 +422,83 @@ namespace Fig
else if (is<ValueType::DoubleClass>()) else if (is<ValueType::DoubleClass>())
return as<ValueType::DoubleClass>(); return as<ValueType::DoubleClass>();
else 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>(); if (is<ValueType::StringClass>()) return as<ValueType::StringClass>();
return toString(); 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::NullClass>()) return String(U"null");
if (is<ValueType::IntClass>()) return FString(std::to_string(as<ValueType::IntClass>())); if (is<ValueType::IntClass>()) return String(std::to_string(as<ValueType::IntClass>()));
if (is<ValueType::DoubleClass>()) return FString(std::format("{}", as<ValueType::DoubleClass>())); if (is<ValueType::DoubleClass>()) return String(std::format("{}", as<ValueType::DoubleClass>()));
if (is<ValueType::StringClass>()) return FString(u8"\"" + as<ValueType::StringClass>() + u8"\""); if (is<ValueType::StringClass>()) return String(String(U"\"") + as<ValueType::StringClass>() + String(U"\""));
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? FString(u8"true") : FString(u8"false"); if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? String(U"true") : String(U"false");
if (is<Function>()) if (is<Function>())
return FString(std::format("<Function '{}'({}) at {:p}>", return String(std::format(
as<Function>().name.toBasicString(), "<Function '{}' at {:p}>", as<Function>().id, static_cast<const void *>(&as<Function>())));
as<Function>().id,
static_cast<const void *>(&as<Function>())));
if (is<StructType>()) if (is<StructType>())
return FString(std::format("<StructType '{}' at {:p}>", return String(std::format("<StructType '{}' at {:p}>",
as<StructType>().type.toString().toBasicString(), as<StructType>().type.toString().toBasicString(),
static_cast<const void *>(&as<StructType>()))); static_cast<const void *>(&as<StructType>())));
if (is<StructInstance>()) if (is<StructInstance>())
return FString(std::format("<StructInstance '{}' at {:p}>", return String(std::format("<StructInstance '{}' at {:p}>",
as<StructInstance>().parentType.toString().toBasicString(), as<StructInstance>().parentType.toString().toBasicString(),
static_cast<const void *>(&as<StructInstance>()))); static_cast<const void *>(&as<StructInstance>())));
if (is<List>()) if (is<List>())
{ {
if (visited.contains(this)) { return u8"[...]"; } if (visited.contains(this)) { return U"[...]"; }
visited.insert(this); visited.insert(this);
FString output(u8"["); String output(U"[");
const List &list = as<List>(); const List &list = as<List>();
bool first_flag = true; bool first_flag = true;
for (auto &ele : list) for (auto &ele : list)
{ {
if (!first_flag) output += u8", "; if (!first_flag) output += U", ";
output += ele.value->toString(visited); output += ele.value->toString(visited);
first_flag = false; first_flag = false;
} }
output += u8"]"; output += U"]";
return output; return output;
} }
if (is<Map>()) if (is<Map>())
{ {
if (visited.contains(this)) { return u8"{...}"; } if (visited.contains(this)) { return U"{...}"; }
visited.insert(this); visited.insert(this);
FString output(u8"{"); String output(U"{");
const Map &map = as<Map>(); const Map &map = as<Map>();
bool first_flag = true; bool first_flag = true;
for (auto &[key, value] : map) for (auto &[key, value] : map)
{ {
if (!first_flag) output += u8", "; if (!first_flag) output += U", ";
output += key.value->toString(visited) + FString(u8" : ") + value->toString(visited); output += key.value->toString(visited) + String(U" : ") + value->toString(visited);
first_flag = false; first_flag = false;
} }
output += u8"}"; output += U"}";
return output; return output;
} }
if (is<Module>()) if (is<Module>())
{ {
return FString(std::format("<Module '{}' at {:p}>", return String(std::format("<Module '{}' at {:p}>",
as<Module>().name.toBasicString(), as<Module>().name.toBasicString(),
static_cast<const void *>(&as<Module>()))); static_cast<const void *>(&as<Module>())));
} }
if (is<InterfaceType>()) if (is<InterfaceType>())
{ {
return FString(std::format("<InterfaceType '{}' at {:p}>", return String(std::format("<InterfaceType '{}' at {:p}>",
as<InterfaceType>().type.toString().toBasicString(), as<InterfaceType>().type.toString().toBasicString(),
static_cast<const void *>(&as<InterfaceType>()))); 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{}; std::unordered_set<const Object *> visited{};
return toString(visited); return toString(visited);
@@ -518,7 +518,7 @@ namespace Fig
friend Object operator+(const Object &lhs, const Object &rhs) friend Object operator+(const Object &lhs, const Object &rhs)
{ {
if (lhs.isNull() || rhs.isNull()) 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()) if (lhs.isNumeric() && rhs.isNumeric())
{ {
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>(); bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
@@ -527,14 +527,14 @@ namespace Fig
return Object(result); return Object(result);
} }
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>()) if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
return Object(FString(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>())); return Object(String(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>()));
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) friend Object operator-(const Object &lhs, const Object &rhs)
{ {
if (lhs.isNull() || rhs.isNull()) 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()) if (lhs.isNumeric() && rhs.isNumeric())
{ {
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>(); bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
@@ -542,13 +542,13 @@ namespace Fig
if (bothInt) return Object(static_cast<ValueType::IntClass>(result)); if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
return Object(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) friend Object operator*(const Object &lhs, const Object &rhs)
{ {
if (lhs.isNull() || rhs.isNull()) 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()) if (lhs.isNumeric() && rhs.isNumeric())
{ {
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>(); bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
@@ -558,22 +558,22 @@ namespace Fig
} }
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::IntClass>()) if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::IntClass>())
{ {
FString result; String result;
const FString &l = lhs.as<ValueType::StringClass>(); const String &l = lhs.as<ValueType::StringClass>();
for (size_t i = 0; i < rhs.getNumericValue(); ++i) { result += l; } for (size_t i = 0; i < rhs.getNumericValue(); ++i) { result += l; }
return Object(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) friend Object operator/(const Object &lhs, const Object &rhs)
{ {
if (lhs.isNull() || rhs.isNull()) 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()) if (lhs.isNumeric() && rhs.isNumeric())
{ {
auto rnv = rhs.getNumericValue(); 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>(); // bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
auto result = lhs.getNumericValue() / rnv; auto result = lhs.getNumericValue() / rnv;
// if (bothInt) // if (bothInt)
@@ -583,18 +583,18 @@ namespace Fig
// DO NOT convert it to INT // DO NOT convert it to INT
return Object(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) friend Object operator%(const Object &lhs, const Object &rhs)
{ {
if (lhs.isNull() || rhs.isNull()) 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>()) if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
{ {
ValueType::IntClass lv = lhs.as<ValueType::IntClass>(); ValueType::IntClass lv = lhs.as<ValueType::IntClass>();
ValueType::IntClass rv = 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 q = lv / rv;
ValueType::IntClass r = lv % rv; ValueType::IntClass r = lv % rv;
@@ -605,25 +605,25 @@ namespace Fig
if (lhs.isNumeric() && rhs.isNumeric()) if (lhs.isNumeric() && rhs.isNumeric())
{ {
auto rnv = rhs.getNumericValue(); 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); auto result = std::fmod(lhs.getNumericValue(), rnv);
return Object(result); return Object(result);
} }
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs))); throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
} }
// logic // logic
friend Object operator&&(const Object &lhs, const Object &rhs) friend Object operator&&(const Object &lhs, const Object &rhs)
{ {
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>()) 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>()); return Object(lhs.as<ValueType::BoolClass>() && rhs.as<ValueType::BoolClass>());
} }
friend Object operator||(const Object &lhs, const Object &rhs) friend Object operator||(const Object &lhs, const Object &rhs)
{ {
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>()) 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>()); return Object(lhs.as<ValueType::BoolClass>() || rhs.as<ValueType::BoolClass>());
} }
@@ -631,24 +631,24 @@ namespace Fig
{ {
if (!v.is<ValueType::BoolClass>()) if (!v.is<ValueType::BoolClass>())
throw ValueError( 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>()); return Object(!v.as<ValueType::BoolClass>());
} }
friend Object operator-(const Object &v) 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::IntClass>()) return Object(-v.as<ValueType::IntClass>());
if (v.is<ValueType::DoubleClass>()) return Object(-v.as<ValueType::DoubleClass>()); if (v.is<ValueType::DoubleClass>()) return Object(-v.as<ValueType::DoubleClass>());
throw ValueError( 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) friend Object operator~(const Object &v)
{ {
if (!v.is<ValueType::IntClass>()) if (!v.is<ValueType::IntClass>())
throw ValueError( 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>()); return Object(~v.as<ValueType::IntClass>());
} }
@@ -667,7 +667,7 @@ namespace Fig
if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() < rhs.getNumericValue(); if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() < rhs.getNumericValue();
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>()) if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
return lhs.as<ValueType::StringClass>() < rhs.as<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) { return lhs == rhs || lhs < rhs; }
friend bool operator>(const Object &lhs, const Object &rhs) friend bool operator>(const Object &lhs, const Object &rhs)
@@ -675,7 +675,7 @@ namespace Fig
if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() > rhs.getNumericValue(); if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() > rhs.getNumericValue();
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>()) if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
return lhs.as<ValueType::StringClass>() > rhs.as<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) { return lhs == rhs || lhs > rhs; }
@@ -683,21 +683,21 @@ namespace Fig
friend Object bit_and(const Object &lhs, const Object &rhs) friend Object bit_and(const Object &lhs, const Object &rhs)
{ {
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>()) 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>()); return Object(lhs.as<ValueType::IntClass>() & rhs.as<ValueType::IntClass>());
} }
friend Object bit_or(const Object &lhs, const Object &rhs) friend Object bit_or(const Object &lhs, const Object &rhs)
{ {
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>()) 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>()); return Object(lhs.as<ValueType::IntClass>() | rhs.as<ValueType::IntClass>());
} }
friend Object bit_xor(const Object &lhs, const Object &rhs) friend Object bit_xor(const Object &lhs, const Object &rhs)
{ {
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>()) 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>()); return Object(lhs.as<ValueType::IntClass>() ^ rhs.as<ValueType::IntClass>());
} }
@@ -705,28 +705,28 @@ namespace Fig
{ {
if (!v.is<ValueType::IntClass>()) if (!v.is<ValueType::IntClass>())
throw ValueError( 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>()); return Object(~v.as<ValueType::IntClass>());
} }
friend Object shift_left(const Object &lhs, const Object &rhs) friend Object shift_left(const Object &lhs, const Object &rhs)
{ {
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>()) 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>()); return Object(lhs.as<ValueType::IntClass>() << rhs.as<ValueType::IntClass>());
} }
friend Object shift_right(const Object &lhs, const Object &rhs) friend Object shift_right(const Object &lhs, const Object &rhs)
{ {
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>()) 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>()); return Object(lhs.as<ValueType::IntClass>() >> rhs.as<ValueType::IntClass>());
} }
friend Object power(const Object &base, const Object &exp) friend Object power(const Object &base, const Object &exp)
{ {
if (base.isNull() || exp.isNull()) 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()) if (base.isNumeric() && exp.isNumeric())
{ {
bool bothInt = base.is<ValueType::IntClass>() && exp.is<ValueType::IntClass>(); bool bothInt = base.is<ValueType::IntClass>() && exp.is<ValueType::IntClass>();
@@ -734,7 +734,7 @@ namespace Fig
if (bothInt) return Object(static_cast<ValueType::IntClass>(result)); if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
return Object(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: public:
using UnaddressableError::UnaddressableError; 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()); std::string msg = std::format("[ValueError] {} in [{}] {}",
return FString(msg); 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/Type.hpp>
#include <Evaluator/Value/structInstance.hpp> #include <Evaluator/Value/structInstance.hpp>
#include <Ast/astBase.hpp> #include <Ast/astBase.hpp>
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Evaluator/Core/StatementResult.hpp> #include <Evaluator/Core/StatementResult.hpp>
#include <Evaluator/Value/value.hpp> #include <Evaluator/Value/value.hpp>
#include <Error/errorLog.hpp> #include <Error/errorLog.hpp>
@@ -50,16 +50,16 @@ namespace Fig
ContextPtr Evaluator::loadModule(const std::filesystem::path &path) 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); std::ifstream file(path);
assert(file.is_open()); assert(file.is_open());
std::vector<Ast::AstBase> asts; std::vector<Ast::AstBase> asts;
std::vector<FString> modSourceLines; std::vector<String> modSourceLines;
if (mod_ast_cache.contains(modSourcePath)) if (mod_ast_cache.contains(modSourcePath))
{ {
@@ -72,9 +72,9 @@ namespace Fig
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close(); 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); Parser parser(lexer, modSourcePath, modSourceLines);
asts = parser.parseAll(); asts = parser.parseAll();
@@ -85,7 +85,7 @@ namespace Fig
evaluator.SetSourcePath(modSourcePath); evaluator.SetSourcePath(modSourcePath);
evaluator.SetSourceLines(modSourceLines); 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.SetGlobalContext(modctx);
evaluator.RegisterBuiltinsValue(); evaluator.RegisterBuiltinsValue();
@@ -96,10 +96,10 @@ namespace Fig
StatementResult Evaluator::evalImportSt(Ast::Import i, ContextPtr ctx) 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 String modName = pathVec.back(); // pathVec at least has 1 element
if (modName == u8"_builtins") if (modName == U"\1")
{ {
RegisterBuiltins(); RegisterBuiltins();
return StatementResult::normal(); return StatementResult::normal();
@@ -109,8 +109,7 @@ namespace Fig
if (ctx->containsInThisScope(modName)) if (ctx->containsInThisScope(modName))
{ {
throw EvaluatorError( throw EvaluatorError(U"\1", std::format("{} has already been declared.", modName.toBasicString()), i);
u8"RedeclarationError", std::format("{} has already been declared.", modName.toBasicString()), i);
} }
auto path = resolveModulePath(pathVec); auto path = resolveModulePath(pathVec);
@@ -124,7 +123,7 @@ namespace Fig
if (ctx->getOpRegistry().contains(type)) if (ctx->getOpRegistry().contains(type))
{ {
throw EvaluatorError( throw EvaluatorError(
u8"DuplicateOperationOverload", U"\1",
std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object", std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object",
modCtx->getScopeName().toBasicString(), modCtx->getScopeName().toBasicString(),
ctx->getScopeName().toBasicString(), ctx->getScopeName().toBasicString(),
@@ -135,7 +134,7 @@ namespace Fig
} }
if (!i->names.empty()) if (!i->names.empty())
{ {
for (const FString &symName : i->names) for (const String &symName : i->names)
{ {
LvObject tmp(modCtx->get(symName), modCtx); LvObject tmp(modCtx->get(symName), modCtx);
const ObjectPtr &value = tmp.get(); const ObjectPtr &value = tmp.get();
@@ -183,13 +182,13 @@ namespace Fig
*/ */
const StructInstance &resInst = result->as<StructInstance>(); 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 = Function(getErrorClassFn.name,
getErrorClassFn.paras, getErrorClassFn.paras,
getErrorClassFn.retType, getErrorClassFn.retType,
getErrorClassFn.body, getErrorClassFn.body,
resInst.localContext); resInst.localContext);
Function getErrorMessageFn = ctx->getImplementedMethod(resultType, u8"getErrorMessage"); Function getErrorMessageFn = ctx->getImplementedMethod(resultType, U"\1");
getErrorMessageFn = Function(getErrorMessageFn.name, getErrorMessageFn = Function(getErrorMessageFn.name,
getErrorMessageFn.paras, getErrorMessageFn.paras,
getErrorMessageFn.retType, getErrorMessageFn.retType,
@@ -210,17 +209,16 @@ namespace Fig
// std::cerr << errorClassRes.unwrap()->toString().toBasicString() << "\n"; // std::cerr << errorClassRes.unwrap()->toString().toBasicString() << "\n";
// std::cerr << errorMessageRes.unwrap()->toString().toBasicString() << "\n"; // std::cerr << errorMessageRes.unwrap()->toString().toBasicString() << "\n";
const FString &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>(); const String &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>();
const FString &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>(); const String &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>();
ErrorLog::logFigErrorInterface(errorClass, errorMessage); ErrorLog::logFigErrorInterface(errorClass, errorMessage);
std::exit(1); std::exit(1);
} }
else else
{ {
throw EvaluatorError(u8"UncaughtExceptionError", throw EvaluatorError(
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), U"\1", std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), stmt);
stmt);
} }
} }

View File

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

View File

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

62
src/IR/IR.hpp Normal file
View File

@@ -0,0 +1,62 @@
#pragma once
#include <Core/String.hpp>
#include <vector>
#include <cstdint>
namespace Fig::IR
{
using Reg = uint16_t;
using Label = uint32_t;
constexpr Reg INVALID_REG = 0xFFFF;
enum class Op : uint8_t
{
// ---- control ----
Nop,
Jmp,
Br, // conditional branch
Ret,
Call,
// ---- arithmetic ----
Add,
Sub,
Mul,
Div,
// ---- compare ----
Lt,
Le,
Gt,
Ge,
Eq,
// ---- data ----
LoadImm, // immediate -> reg
Mov,
};
struct Inst
{
Op op;
Reg dst; // 结果寄存器
Reg a; // operand a
Reg b; // operand b
int64_t imm; // immediate / jump offset
};
struct Function
{
String name;
uint16_t paramCount;
uint16_t localCount; // 不含参数
uint16_t regCount; // param + locals + temps
std::vector<Inst> code;
};
}; // namespace Fig::IR

74
src/IR/IRInterpreter.hpp Normal file
View File

@@ -0,0 +1,74 @@
#pragma once
#include <IR/IR.hpp>
#include <cassert>
namespace Fig::IR
{
struct VirtualMachine
{
std::vector<Function *> functions;
int64_t execute(Function *fn, const int64_t *args)
{
assert(fn != nullptr);
std::vector<int64_t> regs(fn->regCount);
// load params
size_t ip = 0;
while (ip < fn->code.size())
{
const Inst &ins = fn->code[ip++];
switch (ins.op)
{
case Op::Nop: break;
case Op::LoadImm: regs[ins.dst] = ins.imm; break;
case Op::Mov: regs[ins.dst] = regs[ins.a]; break;
case Op::Add: regs[ins.dst] = regs[ins.a] + regs[ins.b]; break;
case Op::Sub: regs[ins.dst] = regs[ins.a] - regs[ins.b]; break;
case Op::Mul: regs[ins.dst] = regs[ins.a] * regs[ins.b]; break;
case Op::Div: regs[ins.dst] = regs[ins.a] / regs[ins.b]; break;
case Op::Lt: regs[ins.dst] = regs[ins.a] < regs[ins.b]; break;
case Op::Le: regs[ins.dst] = regs[ins.a] <= regs[ins.b]; break;
case Op::Gt: regs[ins.dst] = regs[ins.a] > regs[ins.b]; break;
case Op::Ge: regs[ins.dst] = regs[ins.a] >= regs[ins.b]; break;
case Op::Eq: regs[ins.dst] = regs[ins.a] == regs[ins.b]; break;
case Op::Jmp: ip = static_cast<size_t>(static_cast<int64_t>(ip) + ins.imm); break;
case Op::Br:
if (regs[ins.a] == 0) { ip = static_cast<size_t>(static_cast<int64_t>(ip) + ins.imm); }
break;
case Op::Call: {
// currently supports 1-arg call via reg a
Function *callee = functions.at(static_cast<size_t>(ins.imm));
int64_t arg0 = regs[ins.a];
int64_t ret = execute(callee, &arg0);
regs[ins.dst] = ret;
break;
}
case Op::Ret: return regs[ins.a];
}
}
// unreachable normally
return 0;
}
};
}; // namespace Fig::IR

14
src/IR/ir_test_main.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include <IR/IRInterpreter.hpp>
#include <IR/IR.hpp>
int main()
{
using namespace Fig;
IR::VirtualMachine vm;
using namespace IR;
IR::Inst fib_ir[] = {
};
}

View File

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

View File

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

View File

@@ -1,3 +0,0 @@
#pragma once
#include "File/File.hpp"

View File

@@ -1,74 +0,0 @@
#pragma once
#include <cassert>
#include <cstdint>
#include <fstream>
#include <limits>
#include <vector>
namespace Fig::CppLibrary
{
using FileIDType = uint16_t;
struct File
{
FileIDType id;
std::fstream *fs;
};
class FileManager
{
private:
std::vector<File *> handlers;
std::vector<FileIDType> free_handlers;
FileIDType allocated = 0;
public:
static constexpr FileIDType MAX_HANDLERS = std::numeric_limits<FileIDType>::max();
static constexpr unsigned int MAX_FILE_BUF = 961200; // bytes
FileIDType AllocFile(std::fstream *fs)
{
FileIDType id = allocated++;
File *f = new File{.id = id, .fs = fs};
handlers.push_back(f);
return id;
}
void CloseFile(FileIDType id)
{
assert(id < allocated && "CloseHandler: id out of range");
File *f = handlers[id];
if (f == nullptr) { return; }
f->fs->close();
delete f->fs;
delete f;
free_handlers.push_back(id);
handlers[id] = nullptr;
}
File *GetNextFreeFile()
{
// if there is no free handler, create a new one
if (free_handlers.size() > 0)
{
FileIDType id = *free_handlers.begin();
handlers[id] = new File{.id = id, .fs = new std::fstream};
free_handlers.erase(free_handlers.begin());
return handlers[id];
}
return handlers[AllocFile(new std::fstream)];
}
File *GetFile(FileIDType id)
{
assert(id < allocated && "GetFile: id out of range");
return handlers[id];
}
static FileManager &getInstance()
{
static FileManager fm;
return fm;
}
};
}; // namespace Fig::CppLibrary

View File

@@ -1,101 +0,0 @@
/*
Official Module `std.file`
Library/std/file/file.fig
Copyright © 2026 PuqiAR. All rights reserved.
*/
import _builtins;
import std.io;
public struct __OpenMode
{
public App: Int = 1;
public Ate: Int = 2;
public Bin: Int = 4;
public In: Int = 8;
public Out: Int = 16;
public Trunc: Int = 32;
public __openmode_to_string: Map =
{
1 : "App",
2 : "Ate",
4 : "Bin",
8 : "In",
16 : "Out",
32 : "Trunc"
};
}
public const OpenMode := new __OpenMode{};
public func repr_mode(mode: Int) -> String
{
return OpenMode.__openmode_to_string[mode];
}
public struct FileError
{
msg: String;
}
impl Error for FileError
{
getErrorClass()
{
return "FileError";
}
getErrorMessage()
{
return msg;
}
toString()
{
return getErrorClass() + ": " + msg;
}
}
public struct File
{
path: String;
mode: Int;
id: Int;
public func read() -> Any
{
return __fstdfile_read(id);
}
public func write(object: String) -> Null
{
__fstdfile_write(id, object);
}
public func close() -> Null
{
__fstdfile_close(id);
}
public func getID() -> Int
{
return id;
}
}
public func open(path: String, mode: Int)
{
const id := __fstdfile_open(path, mode);
if not __fstdfile_is_open(id)
{
throw new FileError{"File " + path + " open failed"};
}
return new File{
path: path,
mode: mode,
id: id
};
}

View File

@@ -120,7 +120,7 @@ public func formatByListArgs(objects) -> Any
{ {
return null; return null;
} }
if objects.length() < 1 if objects.length() < 1
{ {
throw new FormatError{"Require format string"}; throw new FormatError{"Require format string"};
} }

View File

@@ -5,19 +5,13 @@
#include <Ast/Statements/ControlSt.hpp> #include <Ast/Statements/ControlSt.hpp>
#include <Ast/astBase.hpp> #include <Ast/astBase.hpp>
#include <Ast/functionParameters.hpp> #include <Ast/functionParameters.hpp>
#include <Evaluator/Context/context.hpp>
#include <Core/String.hpp>
#include <Ast/AccessModifier.hpp> #include <Ast/AccessModifier.hpp>
#include <Evaluator/Value/structType.hpp> #include <Evaluator/Value/structType.hpp>
#include <Evaluator/Value/value.hpp> #include <Evaluator/Value/value.hpp>
#include <Evaluator/Value/Type.hpp>
#include <Evaluator/Context/context.hpp>
#include <Module/CppLibrary/CppLibrary.hpp>
#include <Module/builtins.hpp> #include <Module/builtins.hpp>
#include <Core/fig_string.hpp>
#include <cassert>
#include <memory> #include <memory>
#include <print> #include <print>
#include <iostream> #include <iostream>
@@ -30,60 +24,60 @@ namespace Fig::Builtins
{ {
const TypeInfo &getErrorInterfaceTypeInfo() const TypeInfo &getErrorInterfaceTypeInfo()
{ {
static const TypeInfo ErrorInterfaceTypeInfo(u8"Error", true); static const TypeInfo ErrorInterfaceTypeInfo(U"Error", true);
return ErrorInterfaceTypeInfo; return ErrorInterfaceTypeInfo;
} }
const TypeInfo &getTypeErrorStructTypeInfo() const TypeInfo &getTypeErrorStructTypeInfo()
{ {
static const TypeInfo TypeErrorStructTypeInfo(u8"TypeError", true); static const TypeInfo TypeErrorStructTypeInfo(U"TypeError", true);
return TypeErrorStructTypeInfo; return TypeErrorStructTypeInfo;
} }
const TypeInfo &getOperationInterfaceTypeInfo() const TypeInfo &getOperationInterfaceTypeInfo()
{ {
static const TypeInfo OperationInterfaceTypeInfo(u8"Operation", true); static const TypeInfo OperationInterfaceTypeInfo(U"Operation", true);
return OperationInterfaceTypeInfo; return OperationInterfaceTypeInfo;
} }
const std::unordered_map<FString, ObjectPtr> &getBuiltinValues() const std::unordered_map<String, ObjectPtr> &getBuiltinValues()
{ {
static const std::unordered_map<FString, ObjectPtr> builtinValues = { static const std::unordered_map<String, ObjectPtr> builtinValues = {
{u8"null", Object::getNullInstance()}, {U"null", Object::getNullInstance()},
{u8"true", Object::getTrueInstance()}, {U"true", Object::getTrueInstance()},
{u8"false", Object::getFalseInstance()}, {U"false", Object::getFalseInstance()},
{u8"Error", {U"Error",
std::make_shared<Object>(InterfaceType(getErrorInterfaceTypeInfo(), std::make_shared<Object>(InterfaceType(getErrorInterfaceTypeInfo(),
{Ast::InterfaceMethod(u8"toString", {Ast::InterfaceMethod(U"toString",
Ast::FunctionParameters({}, {}), Ast::FunctionParameters({}, {}),
std::make_shared<Ast::VarExprAst>(u8"String"), std::make_shared<Ast::VarExprAst>(U"String"),
nullptr), nullptr),
Ast::InterfaceMethod(u8"getErrorClass", Ast::InterfaceMethod(U"getErrorClass",
Ast::FunctionParameters({}, {}), Ast::FunctionParameters({}, {}),
std::make_shared<Ast::VarExprAst>(u8"String"), std::make_shared<Ast::VarExprAst>(U"String"),
nullptr), nullptr),
Ast::InterfaceMethod(u8"getErrorMessage", Ast::InterfaceMethod(U"getErrorMessage",
Ast::FunctionParameters({}, {}), Ast::FunctionParameters({}, {}),
std::make_shared<Ast::VarExprAst>(u8"String"), std::make_shared<Ast::VarExprAst>(U"String"),
nullptr)}))}, nullptr)}))},
{u8"TypeError", std::make_shared<Object>(StructType( {U"TypeError", std::make_shared<Object>(StructType(
getTypeErrorStructTypeInfo(), getTypeErrorStructTypeInfo(),
std::make_shared<Context>(u8"<Built-in `TypeError`>"), std::make_shared<Context>(U"<Built-in `TypeError`>"),
{Field(AccessModifier::Public, u8"msg", ValueType::String, nullptr)} {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))}, {U"Any", std::make_shared<Object>(StructType(ValueType::Any, nullptr, {}, true))},
{u8"Int", std::make_shared<Object>(StructType(ValueType::Int, nullptr, {}, true))}, {U"Int", std::make_shared<Object>(StructType(ValueType::Int, nullptr, {}, true))},
{u8"Null", std::make_shared<Object>(StructType(ValueType::Null, nullptr, {}, true))}, {U"Null", std::make_shared<Object>(StructType(ValueType::Null, nullptr, {}, true))},
{u8"String", std::make_shared<Object>(StructType(ValueType::String, nullptr, {}, true))}, {U"String", std::make_shared<Object>(StructType(ValueType::String, nullptr, {}, true))},
{u8"Bool", std::make_shared<Object>(StructType(ValueType::Bool, nullptr, {}, true))}, {U"Bool", std::make_shared<Object>(StructType(ValueType::Bool, nullptr, {}, true))},
{u8"Double", std::make_shared<Object>(StructType(ValueType::Double, nullptr, {}, true))}, {U"Double", std::make_shared<Object>(StructType(ValueType::Double, nullptr, {}, true))},
{u8"Function", std::make_shared<Object>(StructType(ValueType::Function, nullptr, {}, true))}, {U"Function", std::make_shared<Object>(StructType(ValueType::Function, nullptr, {}, true))},
{u8"List", std::make_shared<Object>(StructType(ValueType::List, nullptr, {}, true))}, {U"List", std::make_shared<Object>(StructType(ValueType::List, nullptr, {}, true))},
{u8"Map", std::make_shared<Object>(StructType(ValueType::Map, nullptr, {}, true))}, {U"Map", std::make_shared<Object>(StructType(ValueType::Map, nullptr, {}, true))},
// Type `StructType` `StructInstance` `Module` `InterfaceType` // Type `StructType` `StructInstance` `Module` `InterfaceType`
// Not allowed to call constructor! // Not allowed to call constructor!
{u8"type", std::make_shared<Object>(Function( {U"type", std::make_shared<Object>(Function(
u8"type", U"type",
[](const std::vector<ObjectPtr> &_args) -> ObjectPtr [](const std::vector<ObjectPtr> &_args) -> ObjectPtr
{ {
const ObjectPtr &arg = _args[0]; const ObjectPtr &arg = _args[0];
@@ -94,95 +88,86 @@ namespace Fig::Builtins
}; };
return builtinValues; return builtinValues;
} }
const std::unordered_map<FString, int> &getBuiltinFunctionArgCounts() const std::unordered_map<String, int> &getBuiltinFunctionArgCounts()
{ {
static const std::unordered_map<FString, int> builtinFunctionArgCounts = { static const std::unordered_map<String, int> builtinFunctionArgCounts = {
{u8"__fstdout_print", -1}, // variadic {U"__fstdout_print", -1}, // variadic
{u8"__fstdout_println", -1}, // variadic {U"__fstdout_println", -1}, // variadic
{u8"__fstdin_read", 0}, {U"__fstdin_read", 0},
{u8"__fstdin_readln", 0}, {U"__fstdin_readln", 0},
{u8"__fvalue_type", 1}, {U"__fvalue_type", 1},
{u8"__fvalue_int_parse", 1}, {U"__fvalue_int_parse", 1},
{u8"__fvalue_int_from", 1}, {U"__fvalue_int_from", 1},
{u8"__fvalue_double_parse", 1}, {U"__fvalue_double_parse", 1},
{u8"__fvalue_double_from", 1}, {U"__fvalue_double_from", 1},
{u8"__fvalue_string_from", 1}, {U"__fvalue_string_from", 1},
{u8"__ftime_now_ns", 0}, {U"__ftime_now_ns", 0},
/* math start */ /* math start */
{u8"__fmath_acos", 1}, {U"__fmath_acos", 1},
{u8"__fmath_acosh", 1}, {U"__fmath_acosh", 1},
{u8"__fmath_asin", 1}, {U"__fmath_asin", 1},
{u8"__fmath_asinh", 1}, {U"__fmath_asinh", 1},
{u8"__fmath_atan", 1}, {U"__fmath_atan", 1},
{u8"__fmath_atan2", 2}, {U"__fmath_atan2", 2},
{u8"__fmath_atanh", 1}, {U"__fmath_atanh", 1},
{u8"__fmath_ceil", 1}, {U"__fmath_ceil", 1},
{u8"__fmath_cos", 1}, {U"__fmath_cos", 1},
{u8"__fmath_cosh", 1}, {U"__fmath_cosh", 1},
{u8"__fmath_exp", 1}, {U"__fmath_exp", 1},
{u8"__fmath_expm1", 1}, {U"__fmath_expm1", 1},
{u8"__fmath_fabs", 1}, {U"__fmath_fabs", 1},
{u8"__fmath_floor", 1}, {U"__fmath_floor", 1},
{u8"__fmath_fmod", 2}, {U"__fmath_fmod", 2},
{u8"__fmath_frexp", 1}, {U"__fmath_frexp", 1},
{u8"__fmath_gcd", 2}, {U"__fmath_gcd", 2},
{u8"__fmath_hypot", 2}, {U"__fmath_hypot", 2},
{u8"__fmath_isequal", 2}, {U"__fmath_isequal", 2},
{u8"__fmath_log", 1}, {U"__fmath_log", 1},
{u8"__fmath_log10", 1}, {U"__fmath_log10", 1},
{u8"__fmath_log1p", 1}, {U"__fmath_log1p", 1},
{u8"__fmath_log2", 1}, {U"__fmath_log2", 1},
{u8"__fmath_sin", 1}, {U"__fmath_sin", 1},
{u8"__fmath_sinh", 1}, {U"__fmath_sinh", 1},
{u8"__fmath_sqrt", 1}, {U"__fmath_sqrt", 1},
{u8"__fmath_tan", 1}, {U"__fmath_tan", 1},
{u8"__fmath_tanh", 1}, {U"__fmath_tanh", 1},
{u8"__fmath_trunc", 1}, {U"__fmath_trunc", 1},
/* file start */
{u8"__fstdfile_open", 2},
{u8"__fstdfile_close", 1},
{u8"__fstdfile_is_open", 1},
{u8"__fstdfile_read", 1},
{u8"__fstdfile_write", 2},
}; };
return builtinFunctionArgCounts; return builtinFunctionArgCounts;
} }
const std::unordered_map<String, BuiltinFunction> &getBuiltinFunctions()
const std::unordered_map<FString, BuiltinFunction> &getBuiltinFunctions()
{ {
static const std::unordered_map<FString, BuiltinFunction> builtinFunctions{ static const std::unordered_map<String, BuiltinFunction> builtinFunctions{
{u8"__fstdout_print", {U"__fstdout_print",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); } for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
return std::make_shared<Object>(ValueType::IntClass(args.size())); return std::make_shared<Object>(ValueType::IntClass(args.size()));
}}, }},
{u8"__fstdout_println", {U"__fstdout_println",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); } for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
std::print("\n"); std::print("\n");
return std::make_shared<Object>(ValueType::IntClass(args.size())); return std::make_shared<Object>(ValueType::IntClass(args.size()));
}}, }},
{u8"__fstdin_read", {U"__fstdin_read",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
std::string input; std::string input;
std::cin >> input; std::cin >> input;
return std::make_shared<Object>(FString::fromBasicString(input)); return std::make_shared<Object>(String(input));
}}, }},
{u8"__fstdin_readln", {U"__fstdin_readln",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
std::string line; std::string line;
std::getline(std::cin, line); std::getline(std::cin, line);
return std::make_shared<Object>(FString::fromBasicString(line)); return std::make_shared<Object>(String(line));
}}, }},
{u8"__fvalue_type", {U"__fvalue_type",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
return std::make_shared<Object>(args[0]->getTypeInfo().toString()); return std::make_shared<Object>(args[0]->getTypeInfo().toString());
}}, }},
{u8"__fvalue_int_parse", {U"__fvalue_int_parse",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
FString str = args[0]->as<ValueType::StringClass>(); String str = args[0]->as<ValueType::StringClass>();
try try
{ {
ValueType::IntClass val = std::stoi(str.toBasicString()); ValueType::IntClass val = std::stoi(str.toBasicString());
@@ -190,10 +175,10 @@ namespace Fig::Builtins
} }
catch (...) 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 { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
if (val->is<ValueType::DoubleClass>()) if (val->is<ValueType::DoubleClass>())
@@ -208,13 +193,13 @@ namespace Fig::Builtins
} }
else 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()))); val->getTypeInfo().toString().toBasicString())));
} }
}}, }},
{u8"__fvalue_double_parse", {U"__fvalue_double_parse",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
FString str = args[0]->as<ValueType::StringClass>(); String str = args[0]->as<ValueType::StringClass>();
try try
{ {
ValueType::DoubleClass val = std::stod(str.toBasicString()); ValueType::DoubleClass val = std::stod(str.toBasicString());
@@ -222,10 +207,10 @@ namespace Fig::Builtins
} }
catch (...) 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 { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
if (val->is<ValueType::IntClass>()) if (val->is<ValueType::IntClass>())
@@ -240,16 +225,16 @@ namespace Fig::Builtins
} }
else 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()))); val->getTypeInfo().toString().toBasicString())));
} }
}}, }},
{u8"__fvalue_string_from", {U"__fvalue_string_from",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
return std::make_shared<Object>(val->toStringIO()); return std::make_shared<Object>(val->toStringIO());
}}, }},
{u8"__ftime_now_ns", {U"__ftime_now_ns",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
// returns nanoseconds // returns nanoseconds
using namespace Fig::Time; using namespace Fig::Time;
@@ -259,97 +244,97 @@ namespace Fig::Builtins
}}, }},
/* math start */ /* math start */
{u8"__fmath_acos", {U"__fmath_acos",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(acos(d)); return std::make_shared<Object>(acos(d));
}}, }},
{u8"__fmath_acosh", {U"__fmath_acosh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(acosh(d)); return std::make_shared<Object>(acosh(d));
}}, }},
{u8"__fmath_asin", {U"__fmath_asin",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(asin(d)); return std::make_shared<Object>(asin(d));
}}, }},
{u8"__fmath_asinh", {U"__fmath_asinh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(asinh(d)); return std::make_shared<Object>(asinh(d));
}}, }},
{u8"__fmath_atan", {U"__fmath_atan",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(atan(d)); return std::make_shared<Object>(atan(d));
}}, }},
{u8"__fmath_atan2", {U"__fmath_atan2",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass y = args[0]->getNumericValue(); ValueType::DoubleClass y = args[0]->getNumericValue();
ValueType::DoubleClass x = args[1]->getNumericValue(); ValueType::DoubleClass x = args[1]->getNumericValue();
return std::make_shared<Object>(atan2(y, x)); return std::make_shared<Object>(atan2(y, x));
}}, }},
{u8"__fmath_atanh", {U"__fmath_atanh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(atanh(d)); return std::make_shared<Object>(atanh(d));
}}, }},
{u8"__fmath_ceil", {U"__fmath_ceil",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(ceil(d)); return std::make_shared<Object>(ceil(d));
}}, }},
{u8"__fmath_cos", {U"__fmath_cos",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(cos(d)); return std::make_shared<Object>(cos(d));
}}, }},
{u8"__fmath_cosh", {U"__fmath_cosh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(cosh(d)); return std::make_shared<Object>(cosh(d));
}}, }},
{u8"__fmath_exp", {U"__fmath_exp",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(exp(d)); return std::make_shared<Object>(exp(d));
}}, }},
{u8"__fmath_expm1", {U"__fmath_expm1",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(expm1(d)); return std::make_shared<Object>(expm1(d));
}}, }},
{u8"__fmath_fabs", {U"__fmath_fabs",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(fabs(d)); return std::make_shared<Object>(fabs(d));
}}, }},
{u8"__fmath_floor", {U"__fmath_floor",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(floor(d)); return std::make_shared<Object>(floor(d));
}}, }},
{u8"__fmath_fmod", {U"__fmath_fmod",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue();
return std::make_shared<Object>(fmod(x, y)); return std::make_shared<Object>(fmod(x, y));
}}, }},
{u8"__fmath_frexp", {U"__fmath_frexp",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
@@ -357,126 +342,85 @@ namespace Fig::Builtins
return std::make_shared<Object>(List({std::make_shared<Object>(frexp(d, &e)), return std::make_shared<Object>(List({std::make_shared<Object>(frexp(d, &e)),
std::make_shared<Object>(static_cast<ValueType::IntClass>(e))})); std::make_shared<Object>(static_cast<ValueType::IntClass>(e))}));
}}, }},
{u8"__fmath_gcd", {U"__fmath_gcd",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::IntClass x = args[0]->as<ValueType::IntClass>(); ValueType::IntClass x = args[0]->as<ValueType::IntClass>();
ValueType::IntClass y = args[1]->as<ValueType::IntClass>(); ValueType::IntClass y = args[1]->as<ValueType::IntClass>();
return std::make_shared<Object>(std::gcd(x, y)); return std::make_shared<Object>(std::gcd(x, y));
}}, }},
{u8"__fmath_hypot", {U"__fmath_hypot",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue();
return std::make_shared<Object>(hypot(x, y)); return std::make_shared<Object>(hypot(x, y));
}}, }},
{u8"__fmath_isequal", {U"__fmath_isequal",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass x = args[0]->getNumericValue();
ValueType::DoubleClass y = args[1]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue();
static const double epsilon = 1e-9; static const double epsilon = 1e-9;
return std::make_shared<Object>(fabs(x - y) < epsilon); return std::make_shared<Object>(fabs(x - y) < epsilon);
}}, }},
{u8"__fmath_log", {U"__fmath_log",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log(d)); return std::make_shared<Object>(log(d));
}}, }},
{u8"__fmath_log10", {U"__fmath_log10",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log10(d)); return std::make_shared<Object>(log10(d));
}}, }},
{u8"__fmath_log1p", {U"__fmath_log1p",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log1p(d)); return std::make_shared<Object>(log1p(d));
}}, }},
{u8"__fmath_log2", {U"__fmath_log2",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(log2(d)); return std::make_shared<Object>(log2(d));
}}, }},
{u8"__fmath_sin", {U"__fmath_sin",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sin(d)); return std::make_shared<Object>(sin(d));
}}, }},
{u8"__fmath_sinh", {U"__fmath_sinh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sinh(d)); return std::make_shared<Object>(sinh(d));
}}, }},
{u8"__fmath_sqrt", {U"__fmath_sqrt",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(sqrt(d)); return std::make_shared<Object>(sqrt(d));
}}, }},
{u8"__fmath_tan", {U"__fmath_tan",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(tan(d)); return std::make_shared<Object>(tan(d));
}}, }},
{u8"__fmath_tanh", {U"__fmath_tanh",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(tanh(d)); return std::make_shared<Object>(tanh(d));
}}, }},
{u8"__fmath_trunc", {U"__fmath_trunc",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr { [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
ValueType::DoubleClass d = val->getNumericValue(); ValueType::DoubleClass d = val->getNumericValue();
return std::make_shared<Object>(trunc(d)); return std::make_shared<Object>(trunc(d));
}}, }},
/* file start */
{u8"__fstdfile_open",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
const FString &path = args[0]->as<ValueType::StringClass>();
const ValueType::IntClass &mode = args[1]->as<ValueType::IntClass>();
CppLibrary::File *f = CppLibrary::FileManager::getInstance().GetNextFreeFile();
f->fs->open(path.toBasicString(), static_cast<unsigned int>(mode));
return std::make_shared<Object>(static_cast<ValueType::IntClass>(f->id));
}},
{u8"__fstdfile_close",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
const ValueType::IntClass &id = args[0]->as<ValueType::IntClass>();
CppLibrary::FileManager::getInstance().CloseFile(id);
return Object::getNullInstance();
}},
{u8"__fstdfile_is_open",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
const ValueType::IntClass &id = args[0]->as<ValueType::IntClass>();
return std::make_shared<Object>(CppLibrary::FileManager::getInstance().GetFile(id)->fs->is_open());
}},
{u8"__fstdfile_read",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
const ValueType::IntClass &id = args[0]->as<ValueType::IntClass>();
CppLibrary::File *f = CppLibrary::FileManager::getInstance().GetFile(id);
char *buf = new char[CppLibrary::FileManager::MAX_FILE_BUF];
f->fs->read(buf, CppLibrary::FileManager::MAX_FILE_BUF);
return std::make_shared<Object>(ValueType::StringClass(reinterpret_cast<const char8_t *>(buf)));
}},
{u8"__fstdfile_write",
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
const ValueType::IntClass &id = args[0]->as<ValueType::IntClass>();
const ValueType::StringClass &str = args[1]->as<ValueType::StringClass>();
CppLibrary::File *f = CppLibrary::FileManager::getInstance().GetFile(id);
const char *data = reinterpret_cast<const char *>(str.c_str());
f->fs->write(data, str.size());
return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length()));
// bytes wrote
}},
}; };
return builtinFunctions; return builtinFunctions;
} }

View File

@@ -3,14 +3,13 @@
#include <Ast/Expressions/VarExpr.hpp> #include <Ast/Expressions/VarExpr.hpp>
#include <Ast/functionParameters.hpp> #include <Ast/functionParameters.hpp>
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Evaluator/Value/value.hpp> #include <Evaluator/Value/value.hpp>
#include <Core/runtimeTime.hpp> #include <Core/runtimeTime.hpp>
#include <unordered_map> #include <unordered_map>
#include <functional> #include <functional>
#include <vector> #include <vector>
#include <fstream>
namespace Fig namespace Fig
{ {
@@ -35,52 +34,39 @@ namespace Fig
{ {
add(..., ...) -> ...; add(..., ...) -> ...;
} }
*/ */
const TypeInfo &getOperationInterfaceTypeInfo(); 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> &)>; using BuiltinFunction = std::function<ObjectPtr(const std::vector<ObjectPtr> &)>;
const std::unordered_map<FString, int> &getBuiltinFunctionArgCounts(); const std::unordered_map<String, int> &getBuiltinFunctionArgCounts();
const std::unordered_map<String, BuiltinFunction> &getBuiltinFunctions();
/* inline bool isBuiltinFunction(const String &name)
File
*/
struct FileHandler
{
int64_t id;
std::fstream *fs;
};
std::vector<FileHandler *> &getFileHandlers(); // global
const std::unordered_map<FString, BuiltinFunction> &getBuiltinFunctions();
inline bool isBuiltinFunction(const FString &name)
{ {
return getBuiltinFunctions().find(name) != getBuiltinFunctions().end(); return getBuiltinFunctions().find(name) != getBuiltinFunctions().end();
} }
inline BuiltinFunction getBuiltinFunction(const FString &name) inline BuiltinFunction getBuiltinFunction(const String &name)
{ {
auto it = getBuiltinFunctions().find(name); auto it = getBuiltinFunctions().find(name);
if (it == getBuiltinFunctions().end()) 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; return it->second;
} }
inline int getBuiltinFunctionParamCount(const FString &name) inline int getBuiltinFunctionParamCount(const String &name)
{ {
auto it = getBuiltinFunctionArgCounts().find(name); auto it = getBuiltinFunctionArgCounts().find(name);
if (it == getBuiltinFunctionArgCounts().end()) 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; return it->second;
} }

View File

@@ -87,7 +87,7 @@ namespace Fig
bool isConst = (currentToken().getType() == TokenType::Const ? true : false); bool isConst = (currentToken().getType() == TokenType::Const ? true : false);
next(); next();
expect(TokenType::Identifier); expect(TokenType::Identifier);
FString name = currentToken().getValue(); String name = currentToken().getValue();
next(); next();
Ast::Expression declaredType = nullptr; Ast::Expression declaredType = nullptr;
bool hasSpecificType = false; bool hasSpecificType = false;
@@ -102,12 +102,12 @@ namespace Fig
next(); // consume `;`, no using expectConsume here cause we don't need to check again next(); // consume `;`, no using expectConsume here cause we don't need to check again
return makeAst<Ast::VarDefAst>(isPublic, isConst, name, declaredType, nullptr, false); 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; bool followupType = false;
if (isThis(TokenType::Walrus)) if (isThis(TokenType::Walrus))
{ {
if (hasSpecificType) throwAddressableError<SyntaxError>(FString(u8"")); if (hasSpecificType) throwAddressableError<SyntaxError>(String(U"\1"));
followupType = true; followupType = true;
} }
next(); next();
@@ -118,7 +118,7 @@ namespace Fig
ObjectPtr Parser::__parseValue() ObjectPtr Parser::__parseValue()
{ {
FString _val = currentToken().getValue(); String _val = currentToken().getValue();
if (currentToken().getType() == TokenType::LiteralNumber) if (currentToken().getType() == TokenType::LiteralNumber)
{ {
if (_val.contains(u8'.') || _val.contains(u8'e')) if (_val.contains(u8'.') || _val.contains(u8'e'))
@@ -131,7 +131,7 @@ namespace Fig
} }
catch (...) catch (...)
{ {
throwAddressableError<SyntaxError>(FString(u8"Illegal number literal")); throwAddressableError<SyntaxError>(String(U"\1"));
} }
return std::make_shared<Object>(d); return std::make_shared<Object>(d);
} }
@@ -145,7 +145,7 @@ namespace Fig
} }
catch (...) catch (...)
{ {
throwAddressableError<SyntaxError>(FString(u8"Illegal number literal")); throwAddressableError<SyntaxError>(String(U"\1"));
} }
return std::make_shared<Object>(i); return std::make_shared<Object>(i);
} }
@@ -153,7 +153,7 @@ namespace Fig
else if (currentToken().getType() == TokenType::LiteralString) { return std::make_shared<Object>(_val); } else if (currentToken().getType() == TokenType::LiteralString) { return std::make_shared<Object>(_val); }
else if (currentToken().getType() == TokenType::LiteralBool) 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 if (currentToken().getType() == TokenType::LiteralNull) { return Object::getNullInstance(); }
else else
@@ -176,7 +176,7 @@ namespace Fig
Ast::FunctionParameters::PosParasType pp; Ast::FunctionParameters::PosParasType pp;
Ast::FunctionParameters::DefParasType dp; Ast::FunctionParameters::DefParasType dp;
FString variaPara; String variaPara;
while (true) while (true)
{ {
if (isThis(TokenType::RightParen)) if (isThis(TokenType::RightParen))
@@ -184,13 +184,13 @@ namespace Fig
next(); next();
return Ast::FunctionParameters(pp, dp); return Ast::FunctionParameters(pp, dp);
} }
expect(TokenType::Identifier, FString(u8"Identifier or `)`")); // check current expect(TokenType::Identifier, String(U"\1")); // check current
FString pname = currentToken().getValue(); String pname = currentToken().getValue();
next(); // skip pname next(); // skip pname
if (isThis(TokenType::Assign)) // = if (isThis(TokenType::Assign)) // =
{ {
next(); 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)) if (isThis(TokenType::Comma))
{ {
next(); // only skip `,` when it's there next(); // only skip `,` when it's there
@@ -224,16 +224,13 @@ namespace Fig
variaPara = pname; variaPara = pname;
next(); // skip `...` next(); // skip `...`
if (!isThis(TokenType::RightParen)) if (!isThis(TokenType::RightParen))
throwAddressableError<SyntaxError>( throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
u8"Expects right paren, variable parameter function can only have one parameter",
currentAAI.line,
currentAAI.column);
next(); // skip `)` next(); // skip `)`
return Ast::FunctionParameters(variaPara); return Ast::FunctionParameters(variaPara);
} }
else else
{ {
pp.push_back({pname, makeAst<Ast::VarExprAst>(u8"Any")}); pp.push_back({pname, makeAst<Ast::VarExprAst>(U"\1")});
if (isThis(TokenType::Comma)) if (isThis(TokenType::Comma))
{ {
next(); // only skip `,` when it's there next(); // only skip `,` when it's there
@@ -243,7 +240,7 @@ namespace Fig
} }
Ast::FunctionDef Parser::__parseFunctionDef(bool isPublic) Ast::FunctionDef Parser::__parseFunctionDef(bool isPublic)
{ {
FString funcName = currentToken().getValue(); String funcName = currentToken().getValue();
next(); next();
expect(TokenType::LeftParen); expect(TokenType::LeftParen);
Ast::FunctionParameters params = __parseFunctionParameters(); Ast::FunctionParameters params = __parseFunctionParameters();
@@ -262,9 +259,9 @@ namespace Fig
Ast::StructDef Parser::__parseStructDef(bool isPublic) Ast::StructDef Parser::__parseStructDef(bool isPublic)
{ {
// entry: current is struct name // entry: current is struct name
FString structName = currentToken().getValue(); String structName = currentToken().getValue();
next(); next();
expect(TokenType::LeftBrace, u8"struct body"); expect(TokenType::LeftBrace, U"\1");
next(); next();
bool braceClosed = false; bool braceClosed = false;
@@ -281,7 +278,7 @@ namespace Fig
auto __parseStructField = [this](bool isPublic) -> Ast::StructDefField { auto __parseStructField = [this](bool isPublic) -> Ast::StructDefField {
AccessModifier am = AccessModifier::Normal; AccessModifier am = AccessModifier::Normal;
FString fieldName; String fieldName;
if (isThis(TokenType::Identifier)) if (isThis(TokenType::Identifier))
{ {
fieldName = currentToken().getValue(); fieldName = currentToken().getValue();
@@ -291,13 +288,13 @@ namespace Fig
else if (isThis(TokenType::Const)) else if (isThis(TokenType::Const))
{ {
next(); next();
expect(TokenType::Identifier, u8"field name"); expect(TokenType::Identifier, U"\1");
fieldName = currentToken().getValue(); fieldName = currentToken().getValue();
am = (isPublic ? AccessModifier::PublicConst : AccessModifier::Const); am = (isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
} }
else 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; Ast::Expression fieldType = nullptr;
if (isThis(TokenType::Colon)) if (isThis(TokenType::Colon))
@@ -309,7 +306,7 @@ namespace Fig
if (isThis(TokenType::Assign)) if (isThis(TokenType::Assign))
{ {
next(); next();
if (isEOF()) throwAddressableError<SyntaxError>(FString(u8"expect an expression")); if (isEOF()) throwAddressableError<SyntaxError>(String(U"\1"));
initExpr = parseExpression(0); initExpr = parseExpression(0);
} }
expectSemicolon(); expectSemicolon();
@@ -353,7 +350,7 @@ namespace Fig
} }
else else
{ {
throwAddressableError<SyntaxError>(FString("Invalid syntax")); throwAddressableError<SyntaxError>(String("Invalid syntax"));
} }
} }
else if (isThis(TokenType::Function)) else if (isThis(TokenType::Function))
@@ -370,45 +367,22 @@ namespace Fig
else if (isThis(TokenType::Variable)) else if (isThis(TokenType::Variable))
{ {
throwAddressableError<SyntaxError>( 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 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)); return makeAst<Ast::StructDefSt>(isPublic, structName, fields, makeAst<Ast::BlockStatementAst>(stmts));
} }
Ast::InterfaceDef Parser::__parseInterfaceDef(bool isPublic) Ast::InterfaceDef Parser::__parseInterfaceDef(bool isPublic)
{ {
// entry: current is interface name // entry: current is interface name
FString interfaceName = currentToken().getValue(); String interfaceName = currentToken().getValue();
next(); // consume name next(); // consume name
std::vector<Ast::Expression> bundles;
if (isThis(TokenType::Colon))
{
next(); // consume `:`
// parse bundle interfaces
if (isThis(TokenType::LeftBrace))
{
throwAddressableError<SyntaxError>(u8"expect interfaces to bundle");
}
while (true)
{
if (isThis(TokenType::LeftBrace)) { break; }
bundles.push_back(parseExpression(0, TokenType::Plus, TokenType::LeftBrace));
if (isThis(TokenType::Plus))
{
next(); // consume `+`
}
}
}
expect(TokenType::LeftBrace); // `{ expect(TokenType::LeftBrace); // `{
next(); // consume `{` next(); // consume `{`
@@ -423,7 +397,7 @@ namespace Fig
} }
if (isThis(TokenType::Identifier)) if (isThis(TokenType::Identifier))
{ {
FString funcName = currentToken().getValue(); String funcName = currentToken().getValue();
next(); // consume func name next(); // consume func name
expect(TokenType::LeftParen); expect(TokenType::LeftParen);
@@ -447,25 +421,25 @@ namespace Fig
} }
else 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, bundles, methods, isPublic); return makeAst<Ast::InterfaceDefAst>(interfaceName, methods, isPublic);
} }
Ast::Implement Parser::__parseImplement() Ast::Implement Parser::__parseImplement()
{ {
// entry: current is `impl` // entry: current is `impl`
next(); // consume `impl` next(); // consume `impl`
expect(TokenType::Identifier, u8"interface name"); expect(TokenType::Identifier, U"\1");
FString interfaceName = currentToken().getValue(); String interfaceName = currentToken().getValue();
next(); // consume interface name next(); // consume interface name
expect(TokenType::For); expect(TokenType::For);
next(); // consume `for` next(); // consume `for`
expect(TokenType::Identifier, u8"struct name"); expect(TokenType::Identifier, U"\1");
FString structName = currentToken().getValue(); String structName = currentToken().getValue();
next(); // consume name next(); // consume name
expect(TokenType::LeftBrace); // { expect(TokenType::LeftBrace); // {
next(); // consume `{` next(); // consume `{`
@@ -481,7 +455,7 @@ namespace Fig
} }
if (isThis(TokenType::Identifier)) if (isThis(TokenType::Identifier))
{ {
FString funcName = currentToken().getValue(); String funcName = currentToken().getValue();
next(); // consume func name next(); // consume func name
expect(TokenType::LeftParen); expect(TokenType::LeftParen);
Ast::FunctionParameters paras = __parseFunctionParameters(); Ast::FunctionParameters paras = __parseFunctionParameters();
@@ -491,7 +465,7 @@ namespace Fig
} }
else else
{ {
throwAddressableError<SyntaxError>(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); throwAddressableError<SyntaxError>(String(U"\1"), currentAAI.line, currentAAI.column);
} }
} }
@@ -536,16 +510,16 @@ namespace Fig
next(); // consume `catch` next(); // consume `catch`
expect(TokenType::LeftParen); expect(TokenType::LeftParen);
next(); // consume `(` next(); // consume `(`
expect(TokenType::Identifier, u8"error receive var name"); expect(TokenType::Identifier, U"\1");
FString errVarName = currentToken().getValue(); String errVarName = currentToken().getValue();
next(); // consume name next(); // consume name
bool hasType = false; bool hasType = false;
FString errVarType; String errVarType;
if (isThis(TokenType::Colon)) // : if (isThis(TokenType::Colon)) // :
{ {
next(); next();
expect(TokenType::Identifier, u8"error type"); expect(TokenType::Identifier, U"\1");
errVarType = currentToken().getValue(); errVarType = currentToken().getValue();
next(); // consume var type next(); // consume var type
hasType = true; hasType = true;
@@ -565,8 +539,7 @@ namespace Fig
{ {
if (finallyBlock != nullptr) if (finallyBlock != nullptr)
{ {
throwAddressableError<SyntaxError>( throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
u8"Duplicate try finally-block", currentAAI.line, currentAAI.column);
} }
next(); // consume `finally` next(); // consume `finally`
expect(TokenType::LeftBrace); expect(TokenType::LeftBrace);
@@ -602,8 +575,7 @@ namespace Fig
else if (isThis(TokenType::Interface)) { stmt = __parseInterfaceDef(true); } else if (isThis(TokenType::Interface)) { stmt = __parseInterfaceDef(true); }
else else
{ {
throwAddressableError<SyntaxError>( throwAddressableError<SyntaxError>(String(U"\1"));
FString(u8"Expected `var`, `const`, `function`, `struct` or `interface` after `public`"));
} }
} }
else if (isThis(TokenType::Variable) || isThis(TokenType::Const)) { stmt = __parseVarDef(false); } else if (isThis(TokenType::Variable) || isThis(TokenType::Const)) { stmt = __parseVarDef(false); }
@@ -614,22 +586,19 @@ namespace Fig
} }
else if (isThis(TokenType::Struct)) else if (isThis(TokenType::Struct))
{ {
expectPeek(TokenType::Identifier, u8"struct name"); expectPeek(TokenType::Identifier, U"\1");
next(); next();
stmt = __parseStructDef(false); stmt = __parseStructDef(false);
} }
else if (isThis(TokenType::Interface)) else if (isThis(TokenType::Interface))
{ {
expectPeek(TokenType::Identifier, u8"interface name"); expectPeek(TokenType::Identifier, U"\1");
next(); next();
stmt = __parseInterfaceDef(false); stmt = __parseInterfaceDef(false);
} }
else if (isThis(TokenType::Implement)) { stmt = __parseImplement(); } else if (isThis(TokenType::Implement)) { stmt = __parseImplement(); }
else if (isThis(TokenType::If)) { stmt = __parseIf(); } else if (isThis(TokenType::If)) { stmt = __parseIf(); }
else if (isThis(TokenType::Else)) else if (isThis(TokenType::Else)) { throwAddressableError<SyntaxError>(String(U"\1")); }
{
throwAddressableError<SyntaxError>(FString(u8"`else` without matching `if`"));
}
else if (isThis(TokenType::LeftBrace)) { stmt = __parseBlockStatement(); } else if (isThis(TokenType::LeftBrace)) { stmt = __parseBlockStatement(); }
else if (isThis(TokenType::While)) { stmt = __parseWhile(); } else if (isThis(TokenType::While)) { stmt = __parseWhile(); }
else if (isThis(TokenType::For)) { stmt = __parseFor(); } else if (isThis(TokenType::For)) { stmt = __parseFor(); }
@@ -647,7 +616,7 @@ namespace Fig
} }
else else
{ {
throwAddressableError<SyntaxError>(u8"invalid syntax", currentAAI.line, currentAAI.column); throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
} }
return stmt; return stmt;
} }
@@ -747,15 +716,12 @@ namespace Fig
// 2. expression stmti++, foo() // 2. expression stmti++, foo()
// ❌ not allowedif/while/for/block stmt // ❌ not allowedif/while/for/block stmt
if (isThis(TokenType::LeftBrace)) if (isThis(TokenType::LeftBrace)) { throwAddressableError<SyntaxError>(U"\1"); }
{
throwAddressableError<SyntaxError>(u8"BlockStatement cannot be used as for loop increment");
}
if (isThis(TokenType::If) || isThis(TokenType::While) || isThis(TokenType::For) || isThis(TokenType::Return) if (isThis(TokenType::If) || isThis(TokenType::While) || isThis(TokenType::For) || isThis(TokenType::Return)
|| isThis(TokenType::Break) || isThis(TokenType::Continue)) || 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); Ast::Expression exp = parseExpression(0, TokenType::LeftBrace);
@@ -809,7 +775,7 @@ namespace Fig
return makeAst<Ast::BreakSt>(); return makeAst<Ast::BreakSt>();
} }
Ast::VarExpr Parser::__parseVarExpr(FString name) Ast::VarExpr Parser::__parseVarExpr(String name)
{ {
return makeAst<Ast::VarExprAst>(name); return makeAst<Ast::VarExprAst>(name);
} }
@@ -892,7 +858,7 @@ namespace Fig
{ {
// entry: current is `{` // entry: current is `{`
next(); // consume `{` next(); // consume `{`
std::vector<std::pair<FString, Ast::Expression>> args; std::vector<std::pair<String, Ast::Expression>> args;
/* /*
3 ways of calling constructor 3 ways of calling constructor
.1 Person {"Fig", 1, "IDK"}; .1 Person {"Fig", 1, "IDK"};
@@ -916,13 +882,13 @@ namespace Fig
{ {
// 1 Person {"Fig", 1, "IDK"}; // 1 Person {"Fig", 1, "IDK"};
Ast::Expression expr = parseExpression(0, TokenType::Comma, TokenType::RightBrace); 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) else if (mode == 2)
{ {
// 2 Person {name: "Fig", age: 1, sex: "IDK"}; // 2 Person {name: "Fig", age: 1, sex: "IDK"};
expect(TokenType::Identifier); expect(TokenType::Identifier);
FString fieldName = currentToken().getValue(); String fieldName = currentToken().getValue();
next(); // consume identifier next(); // consume identifier
expect(TokenType::Colon); expect(TokenType::Colon);
next(); // consume colon next(); // consume colon
@@ -936,28 +902,22 @@ namespace Fig
else if (!isThis(TokenType::RightBrace)) else if (!isThis(TokenType::RightBrace))
{ {
throwAddressableError<SyntaxError>( throwAddressableError<SyntaxError>(
FString(std::format("Expect `,` or `}}` in struct initialization expression, got {}", String(std::format("Expect `,` or `}}` in struct initialization expression, got {}",
currentToken().toString().toBasicString()))); currentToken().toString().toBasicString())));
} }
} }
bool shorthand = true; bool shorthand = true;
if (mode == 1) if (mode == 1)
{ {
for (auto &[name, exp] : args) for (auto &[name, exp] : args)
{ {
if (!name.empty()) if (!name.empty()) { shorthand = false; }
{ if (exp->getType() != Ast::AstType::VarExpr) { shorthand = false; }
shorthand = false;
}
if (exp->getType() != Ast::AstType::VarExpr)
{
shorthand = false;
}
} }
if (shorthand) if (shorthand)
{ {
mode = 3; // all are identifiers, so it's shorthand mode, not positional mode = 3; // all are identifiers, so it's shorthand mode, not positional
std::vector<std::pair<FString, Ast::Expression>> nargs; std::vector<std::pair<String, Ast::Expression>> nargs;
for (auto &[name, exp] : args) for (auto &[name, exp] : args)
{ {
const Ast::VarExpr var = std::static_pointer_cast<Ast::VarExprAst>(exp); const Ast::VarExpr var = std::static_pointer_cast<Ast::VarExprAst>(exp);
@@ -1010,7 +970,7 @@ namespace Fig
} }
else else
{ {
throwAddressableError<SyntaxError>(FString(u8"Expect ')' or ',' after expression in parentheses")); throwAddressableError<SyntaxError>(String(U"\1"));
} }
return nullptr; // to suppress compiler warning return nullptr; // to suppress compiler warning
} }
@@ -1038,12 +998,12 @@ namespace Fig
Ast::Import Parser::__parseImport() Ast::Import Parser::__parseImport()
{ {
next(); // consume `import` next(); // consume `import`
std::vector<FString> path; std::vector<String> path;
std::vector<FString> names; std::vector<String> names;
FString rename; String rename;
while (true) while (true)
{ {
expect(TokenType::Identifier, u8"package name"); expect(TokenType::Identifier, U"\1");
path.push_back(currentToken().getValue()); path.push_back(currentToken().getValue());
next(); // consume package name next(); // consume package name
if (isThis(TokenType::Semicolon)) { break; } if (isThis(TokenType::Semicolon)) { break; }
@@ -1055,13 +1015,13 @@ namespace Fig
else if (isThis(TokenType::LeftBrace)) { break; } else if (isThis(TokenType::LeftBrace)) { break; }
else else
{ {
throwAddressableError<SyntaxError>(u8"invalid syntax"); throwAddressableError<SyntaxError>(U"\1");
} }
} }
if (isThis(TokenType::As)) if (isThis(TokenType::As))
{ {
next(); // consume `as` next(); // consume `as`
expect(TokenType::Identifier, u8"new name"); expect(TokenType::Identifier, U"\1");
rename = currentToken().getValue(); rename = currentToken().getValue();
next(); // consume name next(); // consume name
} }
@@ -1079,7 +1039,7 @@ namespace Fig
{ {
next(); // consume `,` next(); // consume `,`
} }
expect(TokenType::Identifier, u8"symbol name"); expect(TokenType::Identifier, U"\1");
names.push_back(currentToken().getValue()); names.push_back(currentToken().getValue());
next(); next();
} }
@@ -1094,10 +1054,10 @@ namespace Fig
Ast::Operator op; Ast::Operator op;
Token tok = currentToken(); 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 (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; return lhs;
} }
if (tok.getType() == TokenType::LeftBracket) if (tok.getType() == TokenType::LeftBracket)
@@ -1118,7 +1078,7 @@ namespace Fig
if (currentToken().getType() == TokenType::Identifier) if (currentToken().getType() == TokenType::Identifier)
{ {
// err // err
throwAddressableError<SyntaxError>(FString(u8"Function literal should not have a name")); throwAddressableError<SyntaxError>(String(U"\1"));
} }
expect(TokenType::LeftParen); expect(TokenType::LeftParen);
lhs = __parseFunctionLiteralExpr(); lhs = __parseFunctionLiteralExpr();
@@ -1130,7 +1090,7 @@ namespace Fig
} }
else if (tok.isIdentifier()) else if (tok.isIdentifier())
{ {
FString id = tok.getValue(); String id = tok.getValue();
next(); next();
lhs = __parseVarExpr(id); lhs = __parseVarExpr(id);
} }
@@ -1150,7 +1110,7 @@ namespace Fig
} }
else else
{ {
throwAddressableError<SyntaxError>(FString(u8"Unexpected token in expression:") + tok.toString()); throwAddressableError<SyntaxError>(String(U"\1") + tok.toString());
} }
// infix / (postfix) ? // infix / (postfix) ?
@@ -1161,11 +1121,7 @@ namespace Fig
/* Postfix */ /* Postfix */
if (tok.getType() == TokenType::LeftBrace) if (tok.getType() == TokenType::LeftBrace) { throwAddressableError<SyntaxError>(String(U"\1")); }
{
throwAddressableError<SyntaxError>(
FString(u8"Since Fig v0.4.2, please use new struct{} to avoid syntax ambiguity"));
}
if (tok.getType() == TokenType::LeftParen) if (tok.getType() == TokenType::LeftParen)
{ {
@@ -1188,10 +1144,9 @@ namespace Fig
{ {
next(); // consume '.' next(); // consume '.'
Token idTok = currentToken(); Token idTok = currentToken();
if (!idTok.isIdentifier()) if (!idTok.isIdentifier()) throwAddressableError<SyntaxError>(String(U"\1"));
throwAddressableError<SyntaxError>(FString(u8"Expected identifier after '.'"));
FString member = idTok.getValue(); String member = idTok.getValue();
next(); // consume identifier next(); // consume identifier
lhs = makeAst<Ast::MemberExprAst>(lhs, member); lhs = makeAst<Ast::MemberExprAst>(lhs, member);
@@ -1247,8 +1202,7 @@ namespace Fig
auto stmt = __parseStatement(); auto stmt = __parseStatement();
if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt) if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt)
{ {
throwAddressableError<SyntaxError>( throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
u8"Package must be at the beginning of the file", currentAAI.line, currentAAI.column);
} }
pushNode(stmt); pushNode(stmt);
} }

View File

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

View File

@@ -1,8 +1,7 @@
#include <Evaluator/Value/Type.hpp>
#include <Ast/astBase.hpp> #include <Ast/astBase.hpp>
#include <Error/error.hpp> #include <Error/error.hpp>
#include <Error/errorLog.hpp> #include <Error/errorLog.hpp>
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <Repl/Repl.hpp> #include <Repl/Repl.hpp>
#include <vector> #include <vector>
@@ -12,8 +11,8 @@ namespace Fig
{ {
ostream << getPrompt() << "\n"; ostream << getPrompt() << "\n";
const FString &sourcePath = u8"<stdin>"; const String &sourcePath = U"<stdin>";
const std::vector<FString> &sourceLines{}; const std::vector<String> &sourceLines{};
Evaluator evaluator; Evaluator evaluator;
@@ -24,8 +23,14 @@ namespace Fig
while (true) while (true)
{ {
ostream << "\r>>"; ostream << "\r\n>>";
const FString &line = readline(); const String &line = readline();
if (line.empty())
{
ostream << Object::getNullInstance()->toString().toBasicString();
continue;
}
if (line == u8"!exit") { break; } if (line == u8"!exit") { break; }
Lexer lexer(line, sourcePath, sourceLines); Lexer lexer(line, sourcePath, sourceLines);
@@ -38,10 +43,6 @@ namespace Fig
StatementResult sr = evaluator.Run(program); StatementResult sr = evaluator.Run(program);
ObjectPtr result = sr.result; ObjectPtr result = sr.result;
if (result->is<ValueType::NullClass>())
{
continue;
}
ostream << result->toString().toBasicString() << '\n'; ostream << result->toString().toBasicString() << '\n';
} }
catch (AddressableError &e) catch (AddressableError &e)

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <Lexer/lexer.hpp> #include <Lexer/lexer.hpp>
#include <Core/fig_string.hpp> #include <Core/String.hpp>
#include <string> #include <string>
#include <locale> #include <locale>
#include <cwctype> #include <cwctype>
@@ -11,36 +11,33 @@
namespace Fig::Utils 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; std::vector<String> lines;
FString currentLine; String currentLine;
while (!it.isEnd())
for (char32_t c : source)
{ {
UTF8Char c = *it;
if (c == U'\n') if (c == U'\n')
{ {
lines.push_back(currentLine); lines.push_back(currentLine);
currentLine = FString(u8""); currentLine = String(U"\1");
} }
else else
{ {
currentLine += c.getString(); currentLine += c;
} }
++it;
}
if (!currentLine.empty())
{
lines.push_back(currentLine);
} }
if (!currentLine.empty()) { lines.push_back(currentLine); }
return lines; return lines;
} }
inline std::u32string utf8ToUtf32(const FString &s) inline std::u32string utf8ToUtf32(const String &s)
{ {
std::u32string result; std::u32string result;
size_t i = 0; size_t i = 0;
while (i < s.size()) while (i < s.length())
{ {
char32_t codepoint = 0; char32_t codepoint = 0;
unsigned char c = static_cast<unsigned char>(s[i]); unsigned char c = static_cast<unsigned char>(s[i]);
@@ -57,12 +54,15 @@ namespace Fig::Utils
} }
else if ((c >> 4) == 0xE) 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; i += 3;
} }
else if ((c >> 3) == 0x1E) 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; i += 4;
} }
else else
@@ -74,60 +74,7 @@ namespace Fig::Utils
} }
return result; 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> template <class T>
bool vectorContains(const T &t, const std::vector<T> v) bool vectorContains(const T &t, const std::vector<T> v)
{ {

View File

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

View File

@@ -1,26 +1,37 @@
/* /*
███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████ █████████ █████ █████ █████████ █████████ ██████████ ███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████
░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███ ███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███░░███ ░░███ ███░░░░░███ ███░░░░░███░░███░░░░░ █████████ █████ █████ █████████ █████████ ██████████ ░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███
░ ░███ ░ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░███░███ ░███ ███ ░░░ ░███ ███ ░███ ░███ ███ ░░░ ░███ █ ███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░███ ███░░░░░███░███ ░███ ███░░░░███ ███░░░░░███░░███░░░░░█
░███ ░███████████ ░█████ ░██████ ░███ ░███ ░███ ░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████ ░███ ░███ ░███ ░███ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░██████ ░███ ███
░███ ░███░░░░░███ ░███░░█ ░███░░░█ ░███ ░███ █████ ░███ ░███░░░░░███ ░███ ░░██████ ░███ █████ ░███ ░███ ░███░░░░░███ ░███ █████ ░███░░█ ░░░ ░███ ░███ ░███ ░███ ███ ░░░ ░███ █ ░ ░███ ░███████████ ░██████ ░██████ ░███ ███ ░███
░███ ░███ ░███ ░███ ░ █ ░███ ░ ░███░███ ░███ ░███ ░███ ░███ ░███ ░░█████ ░░███ ███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████ ░███ ░███░░░░███ ░███░░
█████ █████ █████ ██████████ █████ █████ ░░█████████ ███████████ █████ █████ █████ ░█████ ░░█████████ ░░████████ █████ █████ ░░█████████ ██████████ ░███░░░███ ░███ █████ ███ ███░░░░░███ ░███ ░░██████ ███ █████ ░███ ░███ ░███░░░░░███ ░███
░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░ █████ ░███░░█ ░███ ░███ ░███ ░███ ███ ░ ░███ ░░███ ░░███ ░███ █ ░███ ░███ ░███
░░█████ ░░███ ░░███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░ █ █████ █████ █████ ██████████ █████
█████ ░░█████████ ███████████ █████ █████ █████ ░░█████ ░░█████████ ░░████████ █████ █████ ░░█████████
██████████ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░
░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░
.---. .---.
. __.....__ .--. | | _..._ __.....__ . __.....__ .--. | | _..._ __.....__
.'| .-'' '. _.._ |__| .--./) | | .' '. .--./) .--./) .-'' '. .'| .-'' '. _.._ |__| .--./) | | .' '. .--./)
.| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\ /.''\\ / .-''"'-. `. .--./) .-'' '.
.' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | | __ | | | |/ /________\ \ .| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\
.' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _ _ .:--.'. \`-' / | | /.''\\ / .-''"'-. `.
'--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | ' / | / | \ | /("'` \ .-------------' .' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | |
| | | / | | \ '-.____...---. | | | | \ '---. | |`" __ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---. __ | | | |/ /________\ \
| | | | | | `. .' | | |__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .' .' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _
| '.'| | | | `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / | |_|| || `''-...... -' _ .:--.'. \`-' / | |
| / | '. | '. | | \'. __// \ \._,\ '/| | | | \'. __// ' .'| '/\ \._,\ '/\'. __// '--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | '
`'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---' `-' `--' `--' `" `'---' / | / | \ | /("'` \ .-------------' | | | / | | \ '-.____...---. | | | | \ '---. | |`"
__ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---. | | | | | | `. .' | |
|__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .' | '.'| | |
| `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / |
|_|| || `''-...... -' | / | '. | '. | | \'. __// \ \._,\ '/| | | |
\'. __// ' .'| '/\ \._,\ '/\'. __//
`'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---'
`-' `--' `--' `" `'---'
Copyright (C) 2020-2026 PuqiAR 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 addressableErrorCount = 0;
static size_t unaddressableErrorCount = 0; static size_t unaddressableErrorCount = 0;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Time::init(); Time::init();
// init, set start_time (std::chrono::time_point) // init, set start_time (std::chrono::time_point)
argparse::ArgumentParser program("Fig Interpreter", Fig::Core::VERSION.data()); argparse::ArgumentParser program("Fig Interpreter", Fig::Core::VERSION.data());
program.add_argument("source") program.add_argument("source").help("source file to be interpreted").default_value(std::string(""));
.help("source file to be interpreted") program.add_argument("-r", "--repl").help("start repl").default_value(false).implicit_value(true);
.default_value(std::string(""));
program.add_argument("-r", "--repl")
.help("start repl")
.default_value(false)
.implicit_value(true);
// program.add_argument("-v", "--version") // program.add_argument("-v", "--version")
// .help("get the version of Fig Interpreter") // .help("get the version of Fig Interpreter")
// .default_value(false) // .default_value(false)
@@ -87,7 +91,7 @@ int main(int argc, char **argv)
exit(0); exit(0);
} }
Fig::FString sourcePath(program.get<std::string>("source")); Fig::String sourcePath(program.get<std::string>("source"));
if (sourcePath.empty()) if (sourcePath.empty())
{ {
std::cerr << "No source file provided.\n"; 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>()); std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close(); 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; // Token tok;
// while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile) // while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile)
@@ -149,7 +153,7 @@ int main(int argc, char **argv)
evaluator.SetSourcePath(sourcePath); evaluator.SetSourcePath(sourcePath);
evaluator.SetSourceLines(sourceLines); evaluator.SetSourceLines(sourceLines);
evaluator.CreateGlobalContext(); evaluator.CreateGlobalContext();
evaluator.RegisterBuiltinsValue(); evaluator.RegisterBuiltinsValue();
try try
{ {

View File

@@ -27,6 +27,7 @@ end
add_files("src/Core/warning.cpp") add_files("src/Core/warning.cpp")
add_files("src/Core/runtimeTime.cpp") add_files("src/Core/runtimeTime.cpp")
add_files("src/Core/String.cpp")
add_files("src/Lexer/lexer.cpp") add_files("src/Lexer/lexer.cpp")
add_files("src/Parser/parser.cpp") add_files("src/Parser/parser.cpp")
@@ -42,25 +43,27 @@ target("Fig")
set_kind("binary") set_kind("binary")
add_files("src/Evaluator/Core/*.cpp") add_files("src/Evaluator/Core/*.cpp")
add_files("src/VirtualMachine/VirtualMachine.cpp")
add_files("src/Evaluator/evaluator.cpp") add_files("src/Evaluator/evaluator.cpp")
add_files("src/Repl/Repl.cpp") add_files("src/Repl/Repl.cpp")
add_files("src/main.cpp") add_files("src/main.cpp")
set_warnings("all") set_warnings("all")
-- target("vm_test_main") target("vm_test_main")
-- set_kind("binary") set_kind("binary")
-- add_files("src/Bytecode/vm_test_main.cpp") add_files("src/VirtualMachine/VirtualMachine.cpp")
add_files("src/Bytecode/vm_test_main.cpp")
-- set_warnings("all") set_warnings("all")
-- target("ir_test_main") target("ir_test_main")
-- set_kind("binary") set_kind("binary")
-- add_files("src/IR/ir_test_main.cpp") add_files("src/IR/ir_test_main.cpp")
-- set_warnings("all") set_warnings("all")
target("StringTest") target("StringTest")
set_kind("binary") set_kind("binary")