Compare commits
2 Commits
7cad512010
...
generics-a
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f6200f393 | |||
| e7eb194b6c |
@@ -2,11 +2,11 @@ type MyTrait trait {}
|
||||
|
||||
type Pair[K, V: MyTrait] struct {
|
||||
k: K,
|
||||
v: V,
|
||||
v: V
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
value: i64,
|
||||
value: i64
|
||||
}
|
||||
|
||||
impl MyTrait for Value {}
|
||||
@@ -21,7 +21,7 @@ impl [K, V: MyTrait] Pair[K, V] {
|
||||
fn main(): i64 {
|
||||
let a = Pair[i64, Value]{
|
||||
k: 4,
|
||||
v: Value{value: 6},
|
||||
v: Value{value: 6}
|
||||
};
|
||||
return a.get_value[i64](999).value;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ export interface LiteralStruct {
|
||||
name: Identifier;
|
||||
fields: StructField[];
|
||||
type: TypeUsage;
|
||||
typeParameters: GenericUsage;
|
||||
}
|
||||
|
||||
export interface FunctionCall {
|
||||
@@ -55,10 +56,12 @@ export interface StructGetter {
|
||||
source: Expression;
|
||||
attribute: Identifier;
|
||||
type: TypeUsage;
|
||||
typeParameters: GenericUsage;
|
||||
}
|
||||
|
||||
export interface Path {
|
||||
expressionType: "Path";
|
||||
typeParameters: GenericUsage;
|
||||
value:
|
||||
| { type: "Identifier"; name: Identifier }
|
||||
| { type: "Nested"; parent: Path; name: Identifier };
|
||||
@@ -130,6 +133,7 @@ export interface FunctionArgument {
|
||||
|
||||
export interface FunctionDeclaration {
|
||||
name: Identifier;
|
||||
generic: GenericDeclaration;
|
||||
arguments: FunctionArgument[];
|
||||
returnType: TypeUsage;
|
||||
}
|
||||
@@ -157,6 +161,7 @@ export interface StructTypeDeclaration {
|
||||
moduleItem: "StructTypeDeclaration";
|
||||
typeDeclaration: "StructTypeDeclaration";
|
||||
name: Identifier;
|
||||
generic: GenericDeclaration;
|
||||
fields: StructTypeField[];
|
||||
}
|
||||
|
||||
@@ -164,6 +169,7 @@ export interface TraitTypeDeclaration {
|
||||
moduleItem: "TraitTypeDeclaration";
|
||||
typeDeclaration: "TraitTypeDeclaration";
|
||||
name: Identifier;
|
||||
generic: GenericDeclaration;
|
||||
functions: FunctionDeclaration[];
|
||||
}
|
||||
|
||||
@@ -171,6 +177,7 @@ export type TypeDeclaration = StructTypeDeclaration | TraitTypeDeclaration;
|
||||
|
||||
export interface Impl {
|
||||
moduleItem: "Impl";
|
||||
generic: GenericDeclaration;
|
||||
struct: NamedTypeUsage;
|
||||
trait: NamedTypeUsage | null;
|
||||
functions: Function[];
|
||||
@@ -182,8 +189,29 @@ export interface Module {
|
||||
items: ModuleItem[];
|
||||
}
|
||||
|
||||
export interface GenericParameter {
|
||||
name: Identifier;
|
||||
bounds: Identifier[];
|
||||
}
|
||||
|
||||
export interface GenericDeclaration {
|
||||
parameters: GenericParameter[];
|
||||
}
|
||||
|
||||
export interface KnownGenericUsage {
|
||||
genericUsage: "Known";
|
||||
parameters: TypeUsage[];
|
||||
}
|
||||
|
||||
export interface UnknownGenericUsage {
|
||||
genericUsage: "Unknown";
|
||||
}
|
||||
|
||||
export type GenericUsage = UnknownGenericUsage | KnownGenericUsage;
|
||||
|
||||
export interface NamedTypeUsage {
|
||||
typeUsage: "NamedTypeUsage";
|
||||
typeParameters: GenericUsage;
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
@@ -203,6 +231,7 @@ export type TypeUsage = NamedTypeUsage | FunctionTypeUsage | UnknownTypeUsage;
|
||||
export const newVoid: () => TypeUsage = () => {
|
||||
return {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: { genericUsage: "Known", parameters: [] },
|
||||
name: { text: "Void", spanStart: 0, spanEnd: 0 },
|
||||
};
|
||||
};
|
||||
@@ -210,6 +239,7 @@ export const newVoid: () => TypeUsage = () => {
|
||||
export const newNever: () => TypeUsage = () => {
|
||||
return {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: { genericUsage: "Known", parameters: [] },
|
||||
name: { text: "Never", spanStart: 0, spanEnd: 0 },
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,6 +2,10 @@ import * as ohm from "ohm-js";
|
||||
|
||||
export const boringGrammar = ohm.grammar(String.raw`
|
||||
Boringlang {
|
||||
GenericUsage = "[" ListOf<TypeUsage, ","> "]"
|
||||
GenericParameter = identifier ":" ListOf<TypeUsage, "+"> -- conditions
|
||||
| identifier
|
||||
GenericDeclaration = "[" ListOf<GenericParameter, ","> "]"
|
||||
ReturnStatement = "return" Expression ";"
|
||||
LetStatement = "let" identifier (":" TypeUsage)? "=" Expression ";"
|
||||
AssignmentStatement = identifier "=" Expression ";" -- identifier
|
||||
@@ -17,12 +21,12 @@ export const boringGrammar = ohm.grammar(String.raw`
|
||||
LiteralString = "\"" (~"\"" any)* "\""
|
||||
| "'" (~"'" any)* "'"
|
||||
LiteralStructField = identifier ":" Expression
|
||||
LiteralStruct = identifier "{" ListOf<LiteralStructField, ","> "}"
|
||||
LiteralStruct = identifier (GenericUsage)? "{" ListOf<LiteralStructField, ","> "}"
|
||||
identifier = (letter | "_")+(letter | digit | "_")*
|
||||
StructGetter = Expression "." identifier
|
||||
IfExpression = "if" "(" Expression ")" Block ("else" Block)?
|
||||
Path = Path "::" identifier -- nested
|
||||
| identifier -- base
|
||||
Path = Path "::" identifier (GenericUsage)? -- nested
|
||||
| identifier (GenericUsage)? -- base
|
||||
PrimaryExpression = LiteralInt
|
||||
| LiteralFloat
|
||||
| LiteralBool
|
||||
@@ -33,9 +37,9 @@ export const boringGrammar = ohm.grammar(String.raw`
|
||||
| Block
|
||||
| IfExpression
|
||||
| PrimaryExpression
|
||||
MemberExpression = MemberExpression "." identifier -- structGetter
|
||||
MemberExpression = MemberExpression "." identifier (GenericUsage)? -- structGetter
|
||||
| StructExpression
|
||||
CallExpression = CallExpression "." identifier -- structGetter
|
||||
CallExpression = CallExpression "." identifier (GenericUsage)? -- structGetter
|
||||
| CallExpression "(" ListOf<Expression, ","> ")" -- functionCall
|
||||
| MemberExpression "(" ListOf<Expression, ","> ")" -- memberFunctionCall
|
||||
| MemberExpression
|
||||
@@ -47,19 +51,19 @@ export const boringGrammar = ohm.grammar(String.raw`
|
||||
| MultExpression
|
||||
Expression = AddExpression
|
||||
Block = "{" Statement* Expression? "}"
|
||||
NamedTypeUsage = identifier
|
||||
NamedTypeUsage = identifier (GenericUsage)?
|
||||
TypeUsage = NamedTypeUsage
|
||||
| "fn" "(" ListOf<TypeUsage, ","> ")" ":" TypeUsage -- function_tu
|
||||
FunctionArgument = identifier ":" TypeUsage
|
||||
FunctionDeclaration = "fn" identifier "(" ListOf<FunctionArgument, ","> ")" ":" TypeUsage
|
||||
FunctionDeclaration = "fn" identifier (GenericDeclaration)? "(" ListOf<FunctionArgument, ","> ")" ":" TypeUsage
|
||||
Function = FunctionDeclaration Block
|
||||
StructTypeField = identifier ":" TypeUsage
|
||||
StructTypeDeclaration = "type" identifier "struct" "{" ListOf<StructTypeField, ","> "}"
|
||||
StructTypeDeclaration = "type" identifier (GenericDeclaration)? "struct" "{" ListOf<StructTypeField, ","> "}"
|
||||
TraitMethod = FunctionDeclaration ";"
|
||||
TraitTypeDeclaration = "type" identifier "trait" "{" TraitMethod* "}"
|
||||
TraitTypeDeclaration = "type" identifier (GenericDeclaration)? "trait" "{" TraitMethod* "}"
|
||||
TypeDeclaration = StructTypeDeclaration
|
||||
| TraitTypeDeclaration
|
||||
Impl = "impl" (NamedTypeUsage "for")? NamedTypeUsage "{" Function* "}"
|
||||
Impl = "impl" (GenericDeclaration)? (NamedTypeUsage "for")? NamedTypeUsage "{" Function* "}"
|
||||
ModuleItem = Function
|
||||
| TypeDeclaration
|
||||
| Impl
|
||||
|
||||
@@ -8,6 +8,9 @@ import {
|
||||
FunctionCall,
|
||||
FunctionDeclaration,
|
||||
FunctionTypeUsage,
|
||||
GenericDeclaration,
|
||||
GenericParameter,
|
||||
GenericUsage,
|
||||
Identifier,
|
||||
IfExpression,
|
||||
Impl,
|
||||
@@ -44,6 +47,29 @@ function nextUnknown() {
|
||||
|
||||
export const semantics = boringGrammar.createSemantics();
|
||||
semantics.addOperation<any>("toAST", {
|
||||
GenericUsage(_1, typeUsage, _3): GenericUsage {
|
||||
return {
|
||||
genericUsage: "Known",
|
||||
parameters: typeUsage.asIteration().children.map((c) => c.toAST()),
|
||||
};
|
||||
},
|
||||
GenericParameter_conditions(identifier, _2, typeUsage): GenericParameter {
|
||||
return {
|
||||
name: identifier.toAST(),
|
||||
bounds: typeUsage.asIteration().children.map((c) => c.toAST()),
|
||||
};
|
||||
},
|
||||
GenericParameter(identifier): GenericParameter {
|
||||
return {
|
||||
name: identifier.toAST(),
|
||||
bounds: [],
|
||||
};
|
||||
},
|
||||
GenericDeclaration(_1, parameters, _2): GenericDeclaration {
|
||||
return {
|
||||
parameters: parameters.asIteration().children.map((c) => c.toAST()),
|
||||
};
|
||||
},
|
||||
LiteralInt(a): Expression {
|
||||
return {
|
||||
statementType: "Expression",
|
||||
@@ -52,6 +78,7 @@ semantics.addOperation<any>("toAST", {
|
||||
value: this.sourceString,
|
||||
type: {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: { genericUsage: "Known", parameters: [] },
|
||||
name: { text: "i64", spanStart: 0, spanEnd: 0 },
|
||||
},
|
||||
},
|
||||
@@ -66,6 +93,7 @@ semantics.addOperation<any>("toAST", {
|
||||
value: this.sourceString,
|
||||
type: {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: { genericUsage: "Known", parameters: [] },
|
||||
name: { text: "f64", spanStart: 0, spanEnd: 0 },
|
||||
},
|
||||
},
|
||||
@@ -80,6 +108,7 @@ semantics.addOperation<any>("toAST", {
|
||||
value: this.sourceString,
|
||||
type: {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: { genericUsage: "Known", parameters: [] },
|
||||
name: { text: "bool", spanStart: 0, spanEnd: 0 },
|
||||
},
|
||||
},
|
||||
@@ -94,6 +123,7 @@ semantics.addOperation<any>("toAST", {
|
||||
value: text.sourceString,
|
||||
type: {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: { genericUsage: "Known", parameters: [] },
|
||||
name: { text: "String", spanStart: 0, spanEnd: 0 },
|
||||
},
|
||||
},
|
||||
@@ -106,16 +136,25 @@ semantics.addOperation<any>("toAST", {
|
||||
expression: expression.toAST(),
|
||||
};
|
||||
},
|
||||
LiteralStruct(identifier, _2, fields, _4): Expression {
|
||||
LiteralStruct(identifier, genericUsage, _2, fields, _4): Expression {
|
||||
const gu = genericUsage.toAST();
|
||||
return {
|
||||
statementType: "Expression",
|
||||
subExpression: {
|
||||
expressionType: "LiteralStruct",
|
||||
name: identifier.toAST(),
|
||||
typeParameters: gu.length ? gu[0] : { genericUsage: "Unknown" },
|
||||
fields: fields.asIteration().children.map((c) => c.toAST()),
|
||||
type: { typeUsage: "NamedTypeUsage", name: identifier.toAST() },
|
||||
type: {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: gu.length ? gu[0] : { genericUsage: "Unknown" },
|
||||
name: identifier.toAST(),
|
||||
},
|
||||
},
|
||||
type: {
|
||||
typeUsage: "UnknownTypeUsage",
|
||||
name: nextUnknown(),
|
||||
},
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
};
|
||||
},
|
||||
identifier(_1, _2): Identifier {
|
||||
@@ -144,13 +183,15 @@ semantics.addOperation<any>("toAST", {
|
||||
MemberExpression(expression): Expression {
|
||||
return expression.toAST();
|
||||
},
|
||||
MemberExpression_structGetter(expression, _2, identifier): Expression {
|
||||
MemberExpression_structGetter(expression, _2, identifier, genericUsage): Expression {
|
||||
const gu = genericUsage.toAST();
|
||||
return {
|
||||
statementType: "Expression",
|
||||
subExpression: {
|
||||
expressionType: "StructGetter",
|
||||
source: expression.toAST(),
|
||||
attribute: identifier.toAST(),
|
||||
typeParameters: gu.length ? gu[0] : { genericUsage: "Unknown" },
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
},
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
@@ -159,13 +200,15 @@ semantics.addOperation<any>("toAST", {
|
||||
CallExpression(expression): Expression {
|
||||
return expression.toAST();
|
||||
},
|
||||
CallExpression_structGetter(expression, _2, identifier): Expression {
|
||||
CallExpression_structGetter(expression, _2, identifier, genericUsage): Expression {
|
||||
const gu = genericUsage.toAST();
|
||||
return {
|
||||
statementType: "Expression",
|
||||
subExpression: {
|
||||
expressionType: "StructGetter",
|
||||
source: expression.toAST(),
|
||||
attribute: identifier.toAST(),
|
||||
typeParameters: gu.length ? gu[0] : { genericUsage: "Unknown" },
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
},
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
@@ -210,6 +253,7 @@ semantics.addOperation<any>("toAST", {
|
||||
expressionType: "StructGetter",
|
||||
source: expression.toAST(),
|
||||
attribute: identifier.toAST(),
|
||||
typeParameters: { genericUsage: "Unknown" },
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
},
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
@@ -229,15 +273,19 @@ semantics.addOperation<any>("toAST", {
|
||||
type: { typeUsage: "UnknownTypeUsage", name: nextUnknown() },
|
||||
};
|
||||
},
|
||||
Path_base(identifier): Path {
|
||||
Path_base(identifier, genericUsage): Path {
|
||||
const gu = genericUsage.toAST();
|
||||
return {
|
||||
expressionType: "Path",
|
||||
typeParameters: gu.length ? gu[0] : { genericUsage: "Unknown" },
|
||||
value: { type: "Identifier", name: identifier.toAST() },
|
||||
};
|
||||
},
|
||||
Path_nested(basePath, _2, attrIdent): Path {
|
||||
Path_nested(basePath, _2, attrIdent, genericUsage): Path {
|
||||
const gu = genericUsage.toAST();
|
||||
return {
|
||||
expressionType: "Path",
|
||||
typeParameters: gu.length ? gu[0] : { genericUsage: "Unknown" },
|
||||
value: { type: "Nested", parent: basePath.toAST(), name: attrIdent.toAST() },
|
||||
};
|
||||
},
|
||||
@@ -357,9 +405,11 @@ semantics.addOperation<any>("toAST", {
|
||||
}
|
||||
return block;
|
||||
},
|
||||
NamedTypeUsage(name): NamedTypeUsage {
|
||||
NamedTypeUsage(name, genericUsage): NamedTypeUsage {
|
||||
const gu = genericUsage.toAST();
|
||||
return {
|
||||
typeUsage: "NamedTypeUsage",
|
||||
typeParameters: gu.length ? gu[0] : { genericUsage: "Unknown" },
|
||||
name: name.toAST(),
|
||||
};
|
||||
},
|
||||
@@ -379,9 +429,20 @@ semantics.addOperation<any>("toAST", {
|
||||
type: typeUsage.toAST(),
|
||||
};
|
||||
},
|
||||
FunctionDeclaration(_1, identifier, _3, args, _4, _5, returnType): FunctionDeclaration {
|
||||
FunctionDeclaration(
|
||||
_1,
|
||||
identifier,
|
||||
genericDeclaration,
|
||||
_4,
|
||||
args,
|
||||
_5,
|
||||
_6,
|
||||
returnType,
|
||||
): FunctionDeclaration {
|
||||
const gd = genericDeclaration.toAST();
|
||||
return {
|
||||
name: identifier.toAST(),
|
||||
generic: gd.length ? gd[0] : { parameters: [] },
|
||||
arguments: args.asIteration().children.map((c) => c.toAST()),
|
||||
returnType: returnType.toAST(),
|
||||
};
|
||||
@@ -399,32 +460,54 @@ semantics.addOperation<any>("toAST", {
|
||||
type: typeUsage.toAST(),
|
||||
};
|
||||
},
|
||||
StructTypeDeclaration(_1, identifier, _3, _4, fields, _6): StructTypeDeclaration {
|
||||
StructTypeDeclaration(
|
||||
_1,
|
||||
identifier,
|
||||
genericDeclaration,
|
||||
_4,
|
||||
_5,
|
||||
fields,
|
||||
_7,
|
||||
): StructTypeDeclaration {
|
||||
const gd = genericDeclaration.toAST();
|
||||
return {
|
||||
moduleItem: "StructTypeDeclaration",
|
||||
typeDeclaration: "StructTypeDeclaration",
|
||||
name: identifier.toAST(),
|
||||
generic: gd.length ? gd[0] : { parameters: [] },
|
||||
fields: fields.asIteration().children.map((c) => c.toAST()),
|
||||
};
|
||||
},
|
||||
TraitMethod(declaration, _2): FunctionDeclaration {
|
||||
return declaration.toAST();
|
||||
},
|
||||
TraitTypeDeclaration(_1, identifier, _3, _4, methods, _5): TraitTypeDeclaration {
|
||||
TraitTypeDeclaration(
|
||||
_1,
|
||||
identifier,
|
||||
genericDeclaration,
|
||||
_4,
|
||||
_5,
|
||||
methods,
|
||||
_7,
|
||||
): TraitTypeDeclaration {
|
||||
const gd = genericDeclaration.toAST();
|
||||
return {
|
||||
moduleItem: "TraitTypeDeclaration",
|
||||
typeDeclaration: "TraitTypeDeclaration",
|
||||
name: identifier.toAST(),
|
||||
generic: gd.length ? gd[0] : { parameters: [] },
|
||||
functions: methods.asIteration().children.map((c) => c.toAST()),
|
||||
};
|
||||
},
|
||||
TypeDeclaration(declaration): TypeDeclaration {
|
||||
return declaration.toAST();
|
||||
},
|
||||
Impl(_1, trait, _3, struct, _4, methods, _5): Impl {
|
||||
Impl(_1, genericDeclaration, trait, _4, struct, _6, methods, _8): Impl {
|
||||
const tr = trait.toAST();
|
||||
const gd = genericDeclaration.toAST();
|
||||
return {
|
||||
moduleItem: "Impl",
|
||||
generic: gd.length ? gd[0] : { parameters: [] },
|
||||
struct: struct.toAST(),
|
||||
trait: tr.length > 0 ? tr[0] : null,
|
||||
functions: methods.asIteration().children.map((c) => c.toAST()),
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface Context {
|
||||
environment: Record<string, NamedEntity>;
|
||||
}
|
||||
|
||||
export function getAttr(ctx: Context, name: string, field: string) {
|
||||
export function getAttr(ctx: Context, name: string, field: string): TypeUsage {
|
||||
const struct = ctx.environment[name];
|
||||
if (!struct || struct.namedEntity !== "NamedType") {
|
||||
throw Error(`Unknown type ${name}`);
|
||||
|
||||
Reference in New Issue
Block a user