forked from PuqiAR/Fig-TreeWalker
Compare commits
3 Commits
v0.3.7-alp
...
v0.3.9-alp
| Author | SHA1 | Date | |
|---|---|---|---|
| d398d457b5 | |||
| ccf80536b3 | |||
| 13fdbec0c4 |
@@ -4,7 +4,7 @@
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
#define __FCORE_VERSION "0.3.7-alpha"
|
||||
#define __FCORE_VERSION "0.3.9-alpha"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define __FCORE_PLATFORM "Windows"
|
||||
|
||||
21
src/Core/executablePath.hpp
Normal file
21
src/Core/executablePath.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <libloaderapi.h>
|
||||
#endif
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
inline std::filesystem::path getExecutablePath()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wchar_t buffer[MAX_PATH];
|
||||
GetModuleFileNameW(nullptr, buffer, MAX_PATH);
|
||||
return std::filesystem::path(buffer);
|
||||
#else
|
||||
return std::filesystem::canonical("/proc/self/exe");
|
||||
#endif
|
||||
}
|
||||
}; // namespace Fig
|
||||
18
src/Core/runtimeTime.cpp
Normal file
18
src/Core/runtimeTime.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <Core/runtimeTime.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace Fig::Time
|
||||
{
|
||||
Clock::time_point start_time;
|
||||
void init()
|
||||
{
|
||||
static bool flag = false;
|
||||
if (flag)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
start_time = Clock::now();
|
||||
flag = true;
|
||||
}
|
||||
};
|
||||
10
src/Core/runtimeTime.hpp
Normal file
10
src/Core/runtimeTime.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace Fig::Time
|
||||
{
|
||||
using Clock = std::chrono::steady_clock;
|
||||
extern Clock::time_point start_time; // since process start
|
||||
void init();
|
||||
};
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Core/fig_string.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
#include <variant>
|
||||
#include <map>
|
||||
|
||||
@@ -75,6 +76,28 @@ namespace Fig
|
||||
using BoolClass = bool;
|
||||
using NullClass = std::monostate;
|
||||
using StringClass = FString;
|
||||
|
||||
static const std::unordered_set<TypeInfo, TypeInfoHash> builtinTypes
|
||||
{
|
||||
Any,
|
||||
Null,
|
||||
Int,
|
||||
String,
|
||||
Bool,
|
||||
Double,
|
||||
Function,
|
||||
StructType,
|
||||
StructInstance,
|
||||
List,
|
||||
Map,
|
||||
Module,
|
||||
InterfaceType
|
||||
};
|
||||
|
||||
inline bool isTypeBuiltin(const TypeInfo &type)
|
||||
{
|
||||
return builtinTypes.contains(type);
|
||||
}
|
||||
}; // namespace ValueType
|
||||
}; // namespace Fig
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <Ast/Statements/ErrorFlow.hpp>
|
||||
#include "Value/VariableSlot.hpp"
|
||||
#include <Value/VariableSlot.hpp>
|
||||
#include <Value/value.hpp>
|
||||
#include <Ast/AccessModifier.hpp>
|
||||
#include <Ast/Statements/ImplementSt.hpp>
|
||||
@@ -17,10 +17,12 @@
|
||||
#include <Context/context.hpp>
|
||||
#include <Utils/utils.hpp>
|
||||
#include <Parser/parser.hpp>
|
||||
#include <Core/executablePath.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
@@ -39,8 +41,8 @@ namespace Fig
|
||||
}
|
||||
LvObject Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx)
|
||||
{
|
||||
LvObject base = evalLv(me->base, ctx);
|
||||
RvObject baseVal = base.get();
|
||||
// LvObject base = evalLv(me->base, ctx);
|
||||
RvObject baseVal = eval(me->base, ctx);
|
||||
const FString &member = me->member;
|
||||
if (baseVal->getTypeInfo() == ValueType::Module)
|
||||
{
|
||||
@@ -68,7 +70,7 @@ namespace Fig
|
||||
AccessModifier::PublicConst),
|
||||
ctx); // fake l-value
|
||||
}
|
||||
|
||||
|
||||
if (ctx->hasMethodImplemented(baseVal->getTypeInfo(), member))
|
||||
{
|
||||
// builtin type implementation!
|
||||
@@ -193,25 +195,26 @@ namespace Fig
|
||||
switch (exp->getType())
|
||||
{
|
||||
case AstType::VarExpr: {
|
||||
Ast::VarExpr var = std::dynamic_pointer_cast<Ast::VarExprAst>(exp);
|
||||
Ast::VarExpr var = std::static_pointer_cast<Ast::VarExprAst>(exp);
|
||||
assert(var != nullptr);
|
||||
return evalVarExpr(var, ctx);
|
||||
}
|
||||
case AstType::MemberExpr: {
|
||||
Ast::MemberExpr me = std::dynamic_pointer_cast<Ast::MemberExprAst>(exp);
|
||||
Ast::MemberExpr me = std::static_pointer_cast<Ast::MemberExprAst>(exp);
|
||||
assert(me != nullptr);
|
||||
return evalMemberExpr(me, ctx);
|
||||
}
|
||||
case AstType::IndexExpr: {
|
||||
Ast::IndexExpr ie = std::dynamic_pointer_cast<Ast::IndexExprAst>(exp);
|
||||
Ast::IndexExpr ie = std::static_pointer_cast<Ast::IndexExprAst>(exp);
|
||||
assert(ie != nullptr);
|
||||
return evalIndexExpr(ie, ctx);
|
||||
}
|
||||
default: {
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
|
||||
exp);
|
||||
// throw EvaluatorError(
|
||||
// u8"TypeError",
|
||||
// std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
|
||||
// exp);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,6 +300,9 @@ namespace Fig
|
||||
ObjectPtr lhs = eval(lexp, ctx);
|
||||
ObjectPtr rhs = eval(rexp, ctx);
|
||||
|
||||
const TypeInfo &lhsType = lhs->getTypeInfo();
|
||||
const TypeInfo &rhsType = rhs->getTypeInfo();
|
||||
|
||||
if (lhs->is<StructInstance>() && rhs->is<StructType>())
|
||||
{
|
||||
const StructInstance &si = lhs->as<StructInstance>();
|
||||
@@ -309,10 +315,37 @@ namespace Fig
|
||||
const InterfaceType &it = rhs->as<InterfaceType>();
|
||||
return std::make_shared<Object>(implements(si.parentType, it.type, ctx));
|
||||
}
|
||||
|
||||
if (ValueType::isTypeBuiltin(lhsType) && rhsType == ValueType::StructType)
|
||||
{
|
||||
const StructType &st = rhs->as<StructType>();
|
||||
const TypeInfo &type = st.type;
|
||||
/*
|
||||
如果是内置类型(e.g. Int, String)
|
||||
那么 eval出来String这个字,出来的是StructType
|
||||
而出来的StructType.type就不会是一个独立的TypeInfo,而是内置的ValueType::String
|
||||
依次我们可以判断内置类型
|
||||
|
||||
e.g:
|
||||
"123" is String
|
||||
L OP R
|
||||
|
||||
其中 L 类型为 String
|
||||
而 R 类型为 StructType (builtins.hpp) 中注册
|
||||
拿到 R 的 StructType, 其中的 type 为 String
|
||||
*/
|
||||
if (lhs->getTypeInfo() == type)
|
||||
{
|
||||
return Object::getTrueInstance();
|
||||
}
|
||||
return Object::getFalseInstance();
|
||||
}
|
||||
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
std::format("Operator `is` requires an struct instance on left-hand side, got '{}'",
|
||||
lhs->getTypeInfo().toString().toBasicString()),
|
||||
std::format("Unsupported operator `is` for '{}' && '{}'",
|
||||
lhsType.toString().toBasicString(),
|
||||
rhsType.toString().toBasicString()),
|
||||
bin->lexp);
|
||||
}
|
||||
|
||||
@@ -605,27 +638,27 @@ namespace Fig
|
||||
switch (type)
|
||||
{
|
||||
case AstType::ValueExpr: {
|
||||
auto val = std::dynamic_pointer_cast<Ast::ValueExprAst>(exp);
|
||||
auto val = std::static_pointer_cast<Ast::ValueExprAst>(exp);
|
||||
assert(val != nullptr);
|
||||
return val->val;
|
||||
}
|
||||
case AstType::VarExpr: {
|
||||
auto varExpr = std::dynamic_pointer_cast<Ast::VarExprAst>(exp);
|
||||
auto varExpr = std::static_pointer_cast<Ast::VarExprAst>(exp);
|
||||
assert(varExpr != nullptr);
|
||||
return evalVarExpr(varExpr, ctx).get(); // LvObject -> RvObject
|
||||
}
|
||||
case AstType::BinaryExpr: {
|
||||
auto bin = std::dynamic_pointer_cast<Ast::BinaryExprAst>(exp);
|
||||
auto bin = std::static_pointer_cast<Ast::BinaryExprAst>(exp);
|
||||
assert(bin != nullptr);
|
||||
return evalBinary(bin, ctx);
|
||||
}
|
||||
case AstType::UnaryExpr: {
|
||||
auto un = std::dynamic_pointer_cast<Ast::UnaryExprAst>(exp);
|
||||
auto un = std::static_pointer_cast<Ast::UnaryExprAst>(exp);
|
||||
assert(un != nullptr);
|
||||
return evalUnary(un, ctx);
|
||||
}
|
||||
case AstType::TernaryExpr: {
|
||||
auto te = std::dynamic_pointer_cast<Ast::TernaryExprAst>(exp);
|
||||
auto te = std::static_pointer_cast<Ast::TernaryExprAst>(exp);
|
||||
assert(te != nullptr);
|
||||
return evalTernary(te, ctx);
|
||||
}
|
||||
@@ -633,7 +666,7 @@ namespace Fig
|
||||
case AstType::IndexExpr: return evalLv(exp, ctx).get();
|
||||
|
||||
case AstType::FunctionCall: {
|
||||
auto fnCall = std::dynamic_pointer_cast<Ast::FunctionCallExpr>(exp);
|
||||
auto fnCall = std::static_pointer_cast<Ast::FunctionCallExpr>(exp);
|
||||
assert(fnCall != nullptr);
|
||||
|
||||
Ast::Expression callee = fnCall->callee;
|
||||
@@ -658,7 +691,7 @@ namespace Fig
|
||||
return evalFunctionCall(fn, fnCall->arg, fnName, ctx);
|
||||
}
|
||||
case AstType::FunctionLiteralExpr: {
|
||||
auto fnLiteral = std::dynamic_pointer_cast<Ast::FunctionLiteralExprAst>(exp);
|
||||
auto fnLiteral = std::static_pointer_cast<Ast::FunctionLiteralExprAst>(exp);
|
||||
assert(fnLiteral != nullptr);
|
||||
|
||||
Ast::BlockStatement body = nullptr;
|
||||
@@ -688,7 +721,7 @@ namespace Fig
|
||||
return std::make_shared<Object>(std::move(fn));
|
||||
}
|
||||
case AstType::InitExpr: {
|
||||
auto initExpr = std::dynamic_pointer_cast<Ast::InitExprAst>(exp);
|
||||
auto initExpr = std::static_pointer_cast<Ast::InitExprAst>(exp);
|
||||
LvObject structeLv = evalLv(initExpr->structe, ctx);
|
||||
ObjectPtr structTypeVal = structeLv.get();
|
||||
const FString &structName = structeLv.name();
|
||||
@@ -967,7 +1000,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case AstType::ListExpr: {
|
||||
auto lstExpr = std::dynamic_pointer_cast<Ast::ListExprAst>(exp);
|
||||
auto lstExpr = std::static_pointer_cast<Ast::ListExprAst>(exp);
|
||||
assert(lstExpr != nullptr);
|
||||
|
||||
List list;
|
||||
@@ -976,7 +1009,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case AstType::MapExpr: {
|
||||
auto mapExpr = std::dynamic_pointer_cast<Ast::MapExprAst>(exp);
|
||||
auto mapExpr = std::static_pointer_cast<Ast::MapExprAst>(exp);
|
||||
assert(mapExpr != nullptr);
|
||||
|
||||
Map map;
|
||||
@@ -984,9 +1017,14 @@ namespace Fig
|
||||
return std::make_shared<Object>(std::move(map));
|
||||
}
|
||||
|
||||
default: assert(false);
|
||||
return Object::getNullInstance(); // ignore warning
|
||||
default:
|
||||
{
|
||||
throw RuntimeError(FString(
|
||||
std::format("err type of expr: {}", magic_enum::enum_name(type))
|
||||
));
|
||||
}
|
||||
}
|
||||
return Object::getNullInstance(); // ignore warning
|
||||
}
|
||||
StatementResult Evaluator::evalBlockStatement(Ast::BlockStatement block, ContextPtr ctx)
|
||||
{
|
||||
@@ -1004,12 +1042,12 @@ namespace Fig
|
||||
switch (stmt->getType())
|
||||
{
|
||||
case ImportSt: {
|
||||
auto i = std::dynamic_pointer_cast<Ast::ImportSt>(stmt);
|
||||
auto i = std::static_pointer_cast<Ast::ImportSt>(stmt);
|
||||
assert(i != nullptr);
|
||||
return evalImportSt(i, ctx);
|
||||
}
|
||||
case VarDefSt: {
|
||||
auto varDef = std::dynamic_pointer_cast<Ast::VarDefAst>(stmt);
|
||||
auto varDef = std::static_pointer_cast<Ast::VarDefAst>(stmt);
|
||||
assert(varDef != nullptr);
|
||||
|
||||
if (ctx->containsInThisScope(varDef->name))
|
||||
@@ -1050,7 +1088,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case FunctionDefSt: {
|
||||
auto fnDef = std::dynamic_pointer_cast<Ast::FunctionDefSt>(stmt);
|
||||
auto fnDef = std::static_pointer_cast<Ast::FunctionDefSt>(stmt);
|
||||
assert(fnDef != nullptr);
|
||||
|
||||
const FString &fnName = fnDef->name;
|
||||
@@ -1070,7 +1108,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case StructSt: {
|
||||
auto stDef = std::dynamic_pointer_cast<Ast::StructDefSt>(stmt);
|
||||
auto stDef = std::static_pointer_cast<Ast::StructDefSt>(stmt);
|
||||
assert(stDef != nullptr);
|
||||
|
||||
if (ctx->containsInThisScope(stDef->name))
|
||||
@@ -1122,7 +1160,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case InterfaceDefSt: {
|
||||
auto ifd = std::dynamic_pointer_cast<Ast::InterfaceDefAst>(stmt);
|
||||
auto ifd = std::static_pointer_cast<Ast::InterfaceDefAst>(stmt);
|
||||
assert(ifd != nullptr);
|
||||
|
||||
const FString &interfaceName = ifd->name;
|
||||
@@ -1143,7 +1181,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case ImplementSt: {
|
||||
auto ip = std::dynamic_pointer_cast<Ast::ImplementAst>(stmt);
|
||||
auto ip = std::static_pointer_cast<Ast::ImplementAst>(stmt);
|
||||
assert(ip != nullptr);
|
||||
|
||||
TypeInfo structType(ip->structName);
|
||||
@@ -1287,7 +1325,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case IfSt: {
|
||||
auto ifSt = std::dynamic_pointer_cast<Ast::IfSt>(stmt);
|
||||
auto ifSt = std::static_pointer_cast<Ast::IfSt>(stmt);
|
||||
ObjectPtr condVal = eval(ifSt->condition, ctx);
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
@@ -1314,7 +1352,7 @@ namespace Fig
|
||||
return StatementResult::normal();
|
||||
};
|
||||
case WhileSt: {
|
||||
auto whileSt = std::dynamic_pointer_cast<Ast::WhileSt>(stmt);
|
||||
auto whileSt = std::static_pointer_cast<Ast::WhileSt>(stmt);
|
||||
while (true)
|
||||
{
|
||||
ObjectPtr condVal = eval(whileSt->condition, ctx);
|
||||
@@ -1337,7 +1375,7 @@ namespace Fig
|
||||
return StatementResult::normal();
|
||||
};
|
||||
case ForSt: {
|
||||
auto forSt = std::dynamic_pointer_cast<Ast::ForSt>(stmt);
|
||||
auto forSt = std::static_pointer_cast<Ast::ForSt>(stmt);
|
||||
ContextPtr loopContext = std::make_shared<Context>(
|
||||
FString(std::format("<For {}:{}>", forSt->getAAI().line, forSt->getAAI().column)),
|
||||
ctx); // for loop has its own context
|
||||
@@ -1378,7 +1416,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case TrySt: {
|
||||
auto tryst = std::dynamic_pointer_cast<Ast::TrySt>(stmt);
|
||||
auto tryst = std::static_pointer_cast<Ast::TrySt>(stmt);
|
||||
assert(tryst != nullptr);
|
||||
|
||||
ContextPtr tryCtx = std::make_shared<Context>(
|
||||
@@ -1417,7 +1455,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case ThrowSt: {
|
||||
auto ts = std::dynamic_pointer_cast<Ast::ThrowSt>(stmt);
|
||||
auto ts = std::static_pointer_cast<Ast::ThrowSt>(stmt);
|
||||
assert(ts != nullptr);
|
||||
|
||||
ObjectPtr value = eval(ts->value, ctx);
|
||||
@@ -1429,7 +1467,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case ReturnSt: {
|
||||
auto returnSt = std::dynamic_pointer_cast<Ast::ReturnSt>(stmt);
|
||||
auto returnSt = std::static_pointer_cast<Ast::ReturnSt>(stmt);
|
||||
assert(returnSt != nullptr);
|
||||
|
||||
ObjectPtr returnValue = Object::getNullInstance(); // default is null
|
||||
@@ -1462,7 +1500,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
case ExpressionStmt: {
|
||||
auto exprStmt = std::dynamic_pointer_cast<Ast::ExpressionStmtAst>(stmt);
|
||||
auto exprStmt = std::static_pointer_cast<Ast::ExpressionStmtAst>(stmt);
|
||||
assert(exprStmt != nullptr);
|
||||
|
||||
return StatementResult::normal(eval(exprStmt->exp, ctx));
|
||||
@@ -1481,6 +1519,14 @@ namespace Fig
|
||||
static const std::vector<fs::path> defaultLibraryPath{"Library", "Library/fpm"};
|
||||
|
||||
std::vector<fs::path> pathToFind(defaultLibraryPath);
|
||||
|
||||
fs::path interpreterPath = getExecutablePath().parent_path();
|
||||
|
||||
for (fs::path &p : pathToFind)
|
||||
{
|
||||
p = interpreterPath / p; // 相对路径 -> 绝对路径
|
||||
}
|
||||
|
||||
pathToFind.insert(
|
||||
pathToFind.begin(),
|
||||
fs::path(this->sourcePath.toBasicString()).parent_path()); // first search module at the source file path
|
||||
@@ -1632,14 +1678,14 @@ namespace Fig
|
||||
for (auto &ast : asts)
|
||||
{
|
||||
Ast::Expression exp;
|
||||
if ((exp = std::dynamic_pointer_cast<Ast::ExpressionAst>(ast)))
|
||||
if ((exp = std::dynamic_pointer_cast<Ast::ExpressionAst>(ast))) // 保持 dynamic_pointer_cast !
|
||||
{
|
||||
sr = StatementResult::normal(eval(exp, global));
|
||||
}
|
||||
else
|
||||
{
|
||||
// statement
|
||||
Ast::Statement stmt = std::dynamic_pointer_cast<Ast::StatementAst>(ast);
|
||||
Ast::Statement stmt = std::static_pointer_cast<Ast::StatementAst>(ast);
|
||||
assert(stmt != nullptr);
|
||||
sr = evalStatement(stmt, global);
|
||||
if (sr.isError())
|
||||
|
||||
@@ -28,7 +28,7 @@ This software is licensed under the MIT License. See LICENSE.txt for details.
|
||||
*/
|
||||
|
||||
#include <Utils/argparse/argparse.hpp>
|
||||
#include <print>
|
||||
// #include <print>
|
||||
#include <fstream>
|
||||
|
||||
#include <Core/core.hpp>
|
||||
@@ -38,6 +38,7 @@ This software is licensed under the MIT License. See LICENSE.txt for details.
|
||||
#include <Utils/AstPrinter.hpp>
|
||||
#include <Utils/utils.hpp>
|
||||
#include <Error/errorLog.hpp>
|
||||
#include <Core/runtimeTime.hpp>
|
||||
|
||||
static size_t addressableErrorCount = 0;
|
||||
static size_t unaddressableErrorCount = 0;
|
||||
@@ -45,6 +46,10 @@ static size_t unaddressableErrorCount = 0;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Time::init();
|
||||
// init, set start_time (std::chrono::time_point)
|
||||
|
||||
|
||||
argparse::ArgumentParser program("Fig Interpreter", Fig::Core::VERSION.data());
|
||||
program.add_argument("source")
|
||||
.help("source file to be interpreted")
|
||||
|
||||
51
src/Module/Library/std/time/time.fig
Normal file
51
src/Module/Library/std/time/time.fig
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Official Module `time`
|
||||
Library/time/time.fig
|
||||
|
||||
Copyright © 2026 PuqiAR. All rights reserved.
|
||||
*/
|
||||
|
||||
import _builtins; // provides __ftime_now_ns (int64_t)
|
||||
|
||||
|
||||
public struct Time
|
||||
{
|
||||
ns: Int; // int64_t, private
|
||||
|
||||
public func toNanos() -> Int
|
||||
{
|
||||
return ns;
|
||||
}
|
||||
|
||||
public func toMicros() -> Int
|
||||
{
|
||||
return __fvalue_int_from(ns / 1000); // convert double to int
|
||||
}
|
||||
|
||||
public func toMillis() -> Double
|
||||
{
|
||||
return ns / 1000 / 1000;
|
||||
}
|
||||
|
||||
public func toSeconds() -> Double
|
||||
{
|
||||
return ns / 1000 / 1000 / 1000;
|
||||
}
|
||||
|
||||
public func since(other: Time) -> Int
|
||||
{
|
||||
const time_ns := other.toNanos();
|
||||
const result := ns - time_ns;
|
||||
if result < 0
|
||||
{
|
||||
throw "time has reversed! 😢";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// TODO: support `-` operator when Fig supports overload
|
||||
}
|
||||
|
||||
public func now() -> Time
|
||||
{
|
||||
return Time{__ftime_now_ns()};
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Ast/Statements/InterfaceDefSt.hpp"
|
||||
#include "Ast/functionParameters.hpp"
|
||||
#include <Ast/Statements/InterfaceDefSt.hpp>
|
||||
#include <Ast/functionParameters.hpp>
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Value/value.hpp>
|
||||
#include <Core/runtimeTime.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <numeric>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
@@ -65,6 +67,7 @@ namespace Fig
|
||||
{u8"__fvalue_double_parse", 1},
|
||||
{u8"__fvalue_double_from", 1},
|
||||
{u8"__fvalue_string_from", 1},
|
||||
{u8"__ftime_now_ns", 0},
|
||||
/* math start */
|
||||
{u8"__fmath_acos", 1},
|
||||
{u8"__fmath_acosh", 1},
|
||||
@@ -194,6 +197,15 @@ namespace Fig
|
||||
ObjectPtr val = args[0];
|
||||
return std::make_shared<Object>(val->toStringIO());
|
||||
}},
|
||||
{u8"__ftime_now_ns",
|
||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||
// returns nanoseconds
|
||||
using namespace Fig::Time;
|
||||
auto now = Clock::now();
|
||||
return std::make_shared<Object>(static_cast<ValueType::IntClass>(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(now - start_time).count()));
|
||||
}},
|
||||
|
||||
/* math start */
|
||||
{u8"__fmath_acos",
|
||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||
|
||||
@@ -592,6 +592,7 @@ namespace Fig
|
||||
}
|
||||
else if (isThis(TokenType::Struct))
|
||||
{
|
||||
next();
|
||||
stmt = __parseStructDef(true);
|
||||
}
|
||||
else if (isThis(TokenType::Interface))
|
||||
|
||||
Reference in New Issue
Block a user