v0.4.2-alpha
[Fix][Impl] 为了消除类构造带来的语法歧义,同时保持实现简洁和括号省略的语法,自此版本,引入了 `new` 操作符
造成歧义的原方法:
if a == A{}
条件是 a == A,还是 a == A{} ?
因此,现在使用 new a_struct{}来构造类
[Opti] 相较于 Fig v0.4.1-alpha版本,release O3同编译条件下
Fib普通递归法性能提升 ~50%
具体方式:
增加了小整数优化,-128~127的整数现在会直接从IntPool获取而不是新构造
...忘了
[Fix] 类构造 shorthand模式忘写了,现在补上了
[Feat][Impl] 类型声明现在接受一个表达式,原为Identifier。实现 var start: time.Time = time.now() 的效果
这是符合语法和语言特性的支持,类型为一等公民。类似Python的 <class 'type'>
[Impl] 修改了部分错误输出的细节
This commit is contained in:
40
src/Evaluator/Value/IntPool.hpp
Normal file
40
src/Evaluator/Value/IntPool.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "Value/value.hpp"
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Value/value_forward.hpp>
|
||||
#include <Value/Type.hpp>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
class IntPool
|
||||
{
|
||||
private:
|
||||
static constexpr ValueType::IntClass CACHE_MIN = -128;
|
||||
static constexpr ValueType::IntClass CACHE_MAX = 127;
|
||||
|
||||
std::array<ObjectPtr, CACHE_MAX - CACHE_MIN + 1> cache;
|
||||
|
||||
public:
|
||||
IntPool()
|
||||
{
|
||||
for (ValueType::IntClass i = CACHE_MIN; i <= CACHE_MAX; ++i)
|
||||
{
|
||||
cache[i - CACHE_MIN] = std::make_shared<Object>(i);
|
||||
}
|
||||
}
|
||||
ObjectPtr createInt(ValueType::IntClass val) const
|
||||
{
|
||||
if (val >= CACHE_MIN && val <= CACHE_MAX) { return cache[val - CACHE_MIN]; }
|
||||
return std::make_shared<Object>(val);
|
||||
}
|
||||
|
||||
static const IntPool &getInstance()
|
||||
{
|
||||
static IntPool pool;
|
||||
return pool;
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
@@ -87,7 +87,7 @@ namespace Fig
|
||||
std::format("Variable `{}` expects type `{}`, but got '{}'",
|
||||
s->name.toBasicString(),
|
||||
s->declaredType.toString().toBasicString(),
|
||||
v->getTypeInfo().toString().toBasicString())));
|
||||
prettyType(v).toBasicString())));
|
||||
}
|
||||
if (isAccessConst(s->am))
|
||||
{
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
#include <Ast/AccessModifier.hpp>
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Value/Type.hpp>
|
||||
#include <Value/value_forward.hpp>
|
||||
|
||||
#include <memory>
|
||||
namespace Fig
|
||||
{
|
||||
class Object;
|
||||
using ObjectPtr = std::shared_ptr<Object>;
|
||||
|
||||
struct VariableSlot
|
||||
{
|
||||
FString name;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "Value/structType.hpp"
|
||||
#include <Value/Type.hpp>
|
||||
#include <Value/value.hpp>
|
||||
#include <Context/context.hpp>
|
||||
@@ -26,9 +27,7 @@ namespace Fig
|
||||
{
|
||||
if (!typeMap.contains(_name))
|
||||
{
|
||||
throw RuntimeError(FString(std::format(
|
||||
"No type named '{}'",
|
||||
_name.toBasicString())));
|
||||
throw RuntimeError(FString(std::format("No type named '{}'", _name.toBasicString())));
|
||||
// *this = ValueType::String;
|
||||
}
|
||||
id = typeMap.at(name); // may throw
|
||||
@@ -41,10 +40,7 @@ namespace Fig
|
||||
ObjectPtr value = key.value;
|
||||
const TypeInfo &type = value->getTypeInfo();
|
||||
|
||||
if (type == ValueType::Int)
|
||||
{
|
||||
return std::hash<ValueType::IntClass>{}(value->as<ValueType::IntClass>());
|
||||
}
|
||||
if (type == ValueType::Int) { return std::hash<ValueType::IntClass>{}(value->as<ValueType::IntClass>()); }
|
||||
if (type == ValueType::Double)
|
||||
{
|
||||
return std::hash<ValueType::DoubleClass>{}(value->as<ValueType::DoubleClass>());
|
||||
@@ -61,10 +57,7 @@ namespace Fig
|
||||
{
|
||||
auto HashFields = [](std::vector<Field> fields) {
|
||||
size_t r = 0;
|
||||
for (auto &f : fields)
|
||||
{
|
||||
r += std::hash<Field>{}(f);
|
||||
}
|
||||
for (auto &f : fields) { r += std::hash<Field>{}(f); }
|
||||
return r;
|
||||
};
|
||||
const StructType &st = value->as<StructType>();
|
||||
@@ -73,19 +66,30 @@ namespace Fig
|
||||
if (type == ValueType::StructInstance)
|
||||
{
|
||||
const StructInstance &si = value->as<StructInstance>();
|
||||
return std::hash<TypeInfo>{}(si.parentType) + std::hash<uint64_t>{}(reinterpret_cast<uint64_t>(std::addressof(*si.localContext)));
|
||||
return std::hash<TypeInfo>{}(si.parentType)
|
||||
+ std::hash<uint64_t>{}(reinterpret_cast<uint64_t>(std::addressof(*si.localContext)));
|
||||
}
|
||||
assert(false);
|
||||
throw ""; // ignore warning
|
||||
}
|
||||
}
|
||||
|
||||
FString prettyType(std::shared_ptr<const Object> obj)
|
||||
TypeInfo actualType(std::shared_ptr<const Object> obj)
|
||||
{
|
||||
auto t = obj->getTypeInfo();
|
||||
if (t == ValueType::StructInstance)
|
||||
return obj->as<StructInstance>().parentType.toString();
|
||||
return t.toString();
|
||||
|
||||
// dispatch builtin struct types (like Int{}, List{} e.g...)
|
||||
if (t == ValueType::StructType)
|
||||
{
|
||||
return obj->as<StructType>().type;
|
||||
}
|
||||
|
||||
if (t == ValueType::StructInstance) return obj->as<StructInstance>().parentType;
|
||||
return t;
|
||||
}
|
||||
FString prettyType(std::shared_ptr<const Object> obj)
|
||||
{
|
||||
return actualType(obj).toString();
|
||||
}
|
||||
|
||||
const TypeInfo ValueType::Any(FString(u8"Any"), true); // id: 1
|
||||
@@ -102,8 +106,6 @@ namespace Fig
|
||||
const TypeInfo ValueType::Module(FString(u8"Module"), true); // id: 12
|
||||
const TypeInfo ValueType::InterfaceType(FString(u8"InterfaceType"), true); // id: 13
|
||||
|
||||
|
||||
|
||||
bool implements(const TypeInfo &structType, const TypeInfo &interfaceType, ContextPtr ctx)
|
||||
{
|
||||
return ctx->hasImplRegisted(structType, interfaceType);
|
||||
@@ -111,28 +113,25 @@ namespace Fig
|
||||
|
||||
bool isTypeMatch(const TypeInfo &expected, ObjectPtr obj, ContextPtr ctx)
|
||||
{
|
||||
if (expected == ValueType::Any)
|
||||
return true;
|
||||
if (expected == ValueType::Any) return true;
|
||||
|
||||
TypeInfo actual = obj->getTypeInfo();
|
||||
|
||||
if (obj->is<StructInstance>())
|
||||
if (obj->is<StructType>())
|
||||
{
|
||||
const StructType &t = obj->as<StructType>();
|
||||
if (expected == t.type) // the StructType typeinfo
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (obj->is<StructInstance>())
|
||||
{
|
||||
const StructInstance &si = obj->as<StructInstance>();
|
||||
if (si.parentType == expected)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (implements(si.parentType, expected, ctx))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return expected == actual;
|
||||
if (si.parentType == expected) { return true; }
|
||||
if (implements(si.parentType, expected, ctx)) { return true; }
|
||||
}
|
||||
return expected == actual;
|
||||
}
|
||||
|
||||
} // namespace Fig
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <Value/Type.hpp>
|
||||
#include <Value/valueError.hpp>
|
||||
#include <Value/module.hpp>
|
||||
#include <Value/value_forward.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
@@ -31,10 +32,8 @@ namespace Fig
|
||||
static_cast<ValueType::DoubleClass>(std::numeric_limits<ValueType::IntClass>::min());
|
||||
return d > intMaxAsDouble || d < intMinAsDouble;
|
||||
}
|
||||
class Object;
|
||||
using ObjectPtr = std::shared_ptr<Object>;
|
||||
|
||||
|
||||
TypeInfo actualType(std::shared_ptr<const Object> obj);
|
||||
FString prettyType(std::shared_ptr<const Object> obj);
|
||||
|
||||
bool operator==(const Object &, const Object &);
|
||||
@@ -509,7 +508,7 @@ namespace Fig
|
||||
{
|
||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
auto result = lhs.getNumericValue() + rhs.getNumericValue();
|
||||
if (bothInt && !isNumberExceededIntLimit(result))
|
||||
if (bothInt)
|
||||
return Object(static_cast<ValueType::IntClass>(result));
|
||||
return Object(result);
|
||||
}
|
||||
@@ -526,7 +525,7 @@ namespace Fig
|
||||
{
|
||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
auto result = lhs.getNumericValue() - rhs.getNumericValue();
|
||||
if (bothInt && !isNumberExceededIntLimit(result))
|
||||
if (bothInt)
|
||||
return Object(static_cast<ValueType::IntClass>(result));
|
||||
return Object(result);
|
||||
}
|
||||
@@ -541,10 +540,20 @@ namespace Fig
|
||||
{
|
||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
auto result = lhs.getNumericValue() * rhs.getNumericValue();
|
||||
if (bothInt && !isNumberExceededIntLimit(result))
|
||||
if (bothInt)
|
||||
return Object(static_cast<ValueType::IntClass>(result));
|
||||
return Object(result);
|
||||
}
|
||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::IntClass>())
|
||||
{
|
||||
FString result;
|
||||
const FString &l = lhs.as<ValueType::StringClass>();
|
||||
for (size_t i=0; i < rhs.getNumericValue(); ++i)
|
||||
{
|
||||
result += l;
|
||||
}
|
||||
return Object(result);
|
||||
}
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs)));
|
||||
}
|
||||
|
||||
@@ -559,7 +568,7 @@ namespace Fig
|
||||
throw ValueError(FString(makeTypeErrorMessage("Division by zero", "/", lhs, rhs)));
|
||||
// bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
auto result = lhs.getNumericValue() / rnv;
|
||||
// if (bothInt && !isNumberExceededIntLimit(result))
|
||||
// if (bothInt)
|
||||
// return Object(static_cast<ValueType::IntClass>(result));
|
||||
|
||||
// int / int maybe decimals
|
||||
@@ -573,15 +582,24 @@ namespace Fig
|
||||
{
|
||||
if (lhs.isNull() || rhs.isNull())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs)));
|
||||
if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
|
||||
{
|
||||
ValueType::IntClass lv = lhs.as<ValueType::IntClass>();
|
||||
ValueType::IntClass rv = lhs.as<ValueType::IntClass>();
|
||||
if (rv == 0) throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
|
||||
|
||||
ValueType::IntClass q = lv / rv;
|
||||
ValueType::IntClass r = lv % rv;
|
||||
if (r != 0 && ((lv < 0) != (rv < 0))) { q -= 1; }
|
||||
return q;
|
||||
}
|
||||
|
||||
if (lhs.isNumeric() && rhs.isNumeric())
|
||||
{
|
||||
auto rnv = rhs.getNumericValue();
|
||||
if (rnv == 0)
|
||||
throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
|
||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
auto result = std::fmod(lhs.getNumericValue(), rnv);
|
||||
if (bothInt && !isNumberExceededIntLimit(result))
|
||||
return Object(static_cast<ValueType::IntClass>(result));
|
||||
return Object(result);
|
||||
}
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
|
||||
@@ -698,7 +716,7 @@ namespace Fig
|
||||
{
|
||||
bool bothInt = base.is<ValueType::IntClass>() && exp.is<ValueType::IntClass>();
|
||||
auto result = std::pow(base.getNumericValue(), exp.getNumericValue());
|
||||
if (bothInt && !isNumberExceededIntLimit(result))
|
||||
if (bothInt)
|
||||
return Object(static_cast<ValueType::IntClass>(result));
|
||||
return Object(result);
|
||||
}
|
||||
@@ -706,7 +724,6 @@ namespace Fig
|
||||
}
|
||||
};
|
||||
|
||||
using ObjectPtr = std::shared_ptr<Object>;
|
||||
using RvObject = ObjectPtr;
|
||||
|
||||
inline bool operator==(const ValueKey &l, const ValueKey &r)
|
||||
|
||||
10
src/Evaluator/Value/value_forward.hpp
Normal file
10
src/Evaluator/Value/value_forward.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
class Object;
|
||||
|
||||
using ObjectPtr = std::shared_ptr<Object>;
|
||||
}; // namespace Fig
|
||||
Reference in New Issue
Block a user