Skip to content

Commit

Permalink
union + distributive conditional types + fix call convention
Browse files Browse the repository at this point in the history
  • Loading branch information
marcj committed Jun 8, 2022
1 parent 3a46c8d commit c5ddd6c
Show file tree
Hide file tree
Showing 11 changed files with 584 additions and 126 deletions.
35 changes: 35 additions & 0 deletions src/checker/checks.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,41 @@ namespace ts::vm {
if (right->kind == TypeKind::Literal) return to<TypeLiteral>(right)->type == TypeLiteralType::String;
}

if (left->kind == TypeKind::Number) {
if (right->kind == TypeKind::Number) return true;
if (right->kind == TypeKind::Literal) return to<TypeLiteral>(right)->type == TypeLiteralType::Number;
}

if (left->kind == TypeKind::Literal && right->kind == TypeKind::Literal) {
return to<TypeLiteral>(left)->type == to<TypeLiteral>(right)->type &&
to<TypeLiteral>(left)->literal == to<TypeLiteral>(right)->literal;
}

if (left->kind == TypeKind::Union) {
if (right->kind != TypeKind::Union) {
for (auto &&l: to<TypeUnion>(left)->types) {
if (isAssignable(l, right)) return true;
}
return false;
} else {
//e.g.: string|number = string|boolean
const auto leftTypes = to<TypeUnion>(left)->types;
const auto rightTypes = to<TypeUnion>(right)->types;

for (auto &&r: rightTypes) {
bool valid = false;
for (auto &&l: leftTypes) {
if (isAssignable(l, r)) {
valid = true;
break;
};
}
if (!valid) return false;
}
return true;
}
}

return false;
}
}
217 changes: 183 additions & 34 deletions src/checker/compiler.h

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions src/checker/instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ namespace ts::instructions {

Class,

Tuple,
TupleMember,

Union,
Intersection,

Extends, //expected 2 entries on the stack
Condition, //expected 3 entries on the stack
JumpCondition, //expected 1 entry on the stack + two uint16 parameters

/**
* Stack parameter. For each JS variable, JS function, as well as type variables (mapped-type variable for example).
*
Expand All @@ -50,6 +57,17 @@ namespace ts::instructions {
*/
Var,

/**
* Makes sure that in the current variable slot is a type placed if nothing was provided as parameter.
*
* For reach type argument like here `T` a TypeArgument OP is generated.
* Different to Var OP since Var does reserve an entry on the stack, whereas TypeArgument does nothing on the stack per default.
* ```typescript
* type A<T> = T;
* ```
*/
TypeArgument,

/**
* Reserves a type variable on the stack, which contains a type object. Unknown as default.
*
Expand All @@ -63,7 +81,9 @@ namespace ts::instructions {
Return,

Jump,
Distribute, //calls a subroutine for each union member. one parameter (address to subroutine)
Call //call a subroutine and push the result on the stack

};
}

Expand Down
14 changes: 9 additions & 5 deletions src/checker/type_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,19 @@ namespace ts::vm {
struct TypeString: BrandKind<TypeKind::String, Type> {};
struct TypeNumber: BrandKind<TypeKind::Number, Type> {};
struct TypeBigint: BrandKind<TypeKind::Bigint, Type> {};
struct TypeBoolean: BrandKind<TypeKind::Boolean, Type> {};
struct TypeBoolean: BrandKind<TypeKind::Boolean, Type> { };
struct TypeSymbol: BrandKind<TypeKind::Symbol, Type> {};
struct TypeNull: BrandKind<TypeKind::Null, Type> {};
struct TypeUndefined: BrandKind<TypeKind::Undefined, Type> {};

struct TypeUnion: BrandKind<TypeKind::Undefined, Type> {
struct TypeUnion: BrandKind<TypeKind::Union, Type> {
vector<shared<Type>> types;
};

enum class TypeLiteralType {
Number,
String,
Boolean,
Bigint
};

Expand All @@ -116,13 +117,13 @@ namespace ts::vm {
};

template<class T>
sharedOpt<T> to(sharedOpt<Type> p) {
sharedOpt<T> to(const sharedOpt<Type> &p) {
if (!p) return nullptr;
if (T::KIND != TypeKind::Unknown && p->kind != T::KIND) return nullptr;
return reinterpret_pointer_cast<T>(p);
}

string_view stringify(shared < Type > type) {
string stringify(shared < Type > type) {
//todo: recursive types

switch (type->kind) {
Expand All @@ -139,8 +140,11 @@ namespace ts::vm {
auto literal = to<TypeLiteral>(type);
switch (literal->type) {
case TypeLiteralType::String: return string("\"").append(literal->literal).append("\"");
case TypeLiteralType::Number: return literal->literal;
case TypeLiteralType::Number: return string(literal->literal);
case TypeLiteralType::Bigint: return string(literal->literal);
case TypeLiteralType::Boolean: return string(literal->literal);
}
return "unknown-literal";
}
case TypeKind::Union: {
auto t = to<TypeUnion>(type);
Expand Down
Loading

0 comments on commit c5ddd6c

Please sign in to comment.