Add support for tuples

This commit is contained in:
Sam Vervaeck 2022-09-16 12:43:06 +02:00
parent 1ea65236a5
commit cd357e03f5
5 changed files with 90 additions and 6 deletions

View file

@ -59,6 +59,14 @@ export class Analyser {
break;
}
case SyntaxKind.TupleExpression:
{
for (const element of node.elements) {
visit(element, source);
}
break;
}
case SyntaxKind.StructExpression:
{
for (const member of node.members) {

View file

@ -841,6 +841,14 @@ export class Checker {
private inferKindFromTypeExpression(node: TypeExpression, env: KindEnv): Kind {
let kind: Kind;
switch (node.kind) {
case SyntaxKind.TupleTypeExpression:
{
for (const element of node.elements) {
this.unifyKind(this.inferKindFromTypeExpression(element, env), new KStar(), node);
}
kind = new KStar();
break;
}
case SyntaxKind.ArrowTypeExpression:
{
for (const param of node.paramTypeExprs) {
@ -1250,6 +1258,9 @@ export class Checker {
return resultType;
}
case SyntaxKind.TupleExpression:
return new TTuple(node.elements.map(el => this.inferExpression(el)), node);
case SyntaxKind.ReferenceExpression:
{
assert(node.modulePath.length === 0);
@ -1407,6 +1418,12 @@ export class Checker {
break;
}
case SyntaxKind.TupleTypeExpression:
{
type = new TTuple(node.elements.map(el => this.inferTypeExpression(el)), node);
break;
}
case SyntaxKind.NestedTypeExpression:
return this.inferTypeExpression(node.typeExpr, introduceTypeVars);
@ -1969,8 +1986,20 @@ export class Checker {
return success;
}
if (right.kind === TypeKind.Arrow) {
return unify(right, left);
if (left.kind === TypeKind.Tuple && right.kind === TypeKind.Tuple) {
if (left.elementTypes.length === right.elementTypes.length) {
let success = false;
const count = left.elementTypes.length;
for (let i = 0; i < count; i++) {
if (!unify(left.elementTypes[i], right.elementTypes[i])) {
success = false;
}
}
if (success) {
TypeBase.join(left, right);
}
return success;
}
}
if (left.kind === TypeKind.Con && right.kind === TypeKind.Con) {

View file

@ -112,6 +112,7 @@ export const enum SyntaxKind {
VarTypeExpression,
AppTypeExpression,
NestedTypeExpression,
TupleTypeExpression,
// Patterns
BindPattern,
@ -1007,6 +1008,28 @@ export class ArrowTypeExpression extends SyntaxBase {
}
export class TupleTypeExpression extends SyntaxBase {
public readonly kind = SyntaxKind.TupleTypeExpression;
public constructor(
public lparen: LParen,
public elements: TypeExpression[],
public rparen: RParen,
) {
super();
}
public getFirstToken(): Token {
return this.lparen;
}
public getLastToken(): Token {
return this.rparen;
}
}
export class ReferenceTypeExpression extends SyntaxBase {
public readonly kind = SyntaxKind.ReferenceTypeExpression;
@ -1103,6 +1126,7 @@ export type TypeExpression
| VarTypeExpression
| AppTypeExpression
| NestedTypeExpression
| TupleTypeExpression
export class BindPattern extends SyntaxBase {

View file

@ -190,7 +190,7 @@ export function describeType(type: Type): string {
else out += ', ';
out += describeType(elementType);
}
return out;
return out + ')';
}
case TypeKind.Nominal:
{

View file

@ -58,6 +58,7 @@ import {
MatchExpression,
LiteralPattern,
DisjunctivePattern,
TupleTypeExpression,
} from "./cst"
import { Stream } from "./util";
@ -185,9 +186,30 @@ export class Parser {
case SyntaxKind.LParen:
{
this.getToken();
const elements = [];
let rparen;
for (;;) {
const t2 = this.peekToken();
if (t2.kind === SyntaxKind.RParen) {
rparen = t2;
break;
}
const typeExpr = this.parseTypeExpression();
const t2 = this.expectToken(SyntaxKind.RParen);
return new NestedTypeExpression(t0, typeExpr, t2);
elements.push(typeExpr);
const t3 = this.getToken();
if (t3.kind === SyntaxKind.RParen) {
rparen = t3;
break;
} else if (t3.kind === SyntaxKind.Comma) {
continue;
} else {
this.raiseParseError(t3, [ SyntaxKind.Comma, SyntaxKind.RParen ]);
}
}
if (elements.length === 1) {
return new NestedTypeExpression(t0, elements[0], rparen);
}
return new TupleTypeExpression(t0, elements, rparen);
}
case SyntaxKind.IdentifierAlt:
return this.parseReferenceTypeExpression();
@ -204,6 +226,7 @@ export class Parser {
if (t1.kind === SyntaxKind.RParen
|| t1.kind === SyntaxKind.RBrace
|| t1.kind === SyntaxKind.RBracket
|| t1.kind === SyntaxKind.Comma
|| t1.kind === SyntaxKind.Equals
|| t1.kind === SyntaxKind.BlockStart
|| t1.kind === SyntaxKind.LineFoldEnd