Skip to content

Commit

Permalink
tcr/num: Introduce Num typeclass and Int64 type
Browse files Browse the repository at this point in the history
Towards #6
  • Loading branch information
lorenzleutgeb committed Nov 14, 2022
1 parent b34f3b4 commit c17d425
Show file tree
Hide file tree
Showing 14 changed files with 335 additions and 56 deletions.
3 changes: 3 additions & 0 deletions src/main/antlr/xyz/leutgeb/lorenz/atlas/antlr/Splay.g4
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ expression : identifier # variableExpression
| PAREN_OPEN expression PAREN_CLOSE # parenthesizedExpression
| NUMBER # constant
| left=expression op right=expression # comparison
| left=expression arithOp right=expression # arithExpression
| TILDE (numerator=NUMBER)? (DIV denominator=NUMBER)? expression # tickExpression
| COIN (numerator=NUMBER)? (DIV denominator=NUMBER)? # coinExpression
| UNDERSCORE # holeExpression
Expand All @@ -62,6 +63,8 @@ expression : identifier # variableExpression

op : EQ | NE | LT | LE | GT | GE ;

arithOp : PLUS | MINUS | CROSS | DIV ;

// For patterns we only admit simpler tuples:
// - non-recursive, i.e. it is only possible to match one level of a tree
// - no derived identifiers
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/xyz/leutgeb/lorenz/atlas/ast/ArithmeticOperator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package xyz.leutgeb.lorenz.atlas.ast;

import java.io.PrintStream;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;

import static java.util.function.Predicate.isEqual;

public enum ArithmeticOperator {
PLUS(List.of("+")),
MINUS(List.of("-")),
TIMES(List.of("*", "⨯")),
DIV(List.of("/"));

private final List<String> tokens;

ArithmeticOperator(List<String> tokens) {
if (tokens.isEmpty()) {
throw new IllegalArgumentException();
}
this.tokens = Collections.unmodifiableList(tokens);
}

public static ArithmeticOperator fromToken(String token) {
for (ArithmeticOperator op : ArithmeticOperator.values()) {
if (op.tokens.stream().anyMatch(isEqual(token))) {
return op;
}
}
throw new IllegalArgumentException();
}

public void printTo(PrintStream out) {
out.print(tokens.get(0));
}

public void printHaskellTo(PrintStream out) {
printTo(out);
}

public void printJavaTo(String x, String y, PrintStream out) {
out.print(x);
out.print(" ");
printTo(out);
out.print(" ");
out.print(y);
}

@Override
public String toString() {
return tokens.get(0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package xyz.leutgeb.lorenz.atlas.ast.expressions;

import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.Value;
import xyz.leutgeb.lorenz.atlas.ast.ArithmeticOperator;
import xyz.leutgeb.lorenz.atlas.ast.Normalization;
import xyz.leutgeb.lorenz.atlas.ast.sources.Derived;
import xyz.leutgeb.lorenz.atlas.ast.sources.Source;
import xyz.leutgeb.lorenz.atlas.typing.simple.TypeClass;
import xyz.leutgeb.lorenz.atlas.typing.simple.TypeConstraint;
import xyz.leutgeb.lorenz.atlas.typing.simple.TypeError;
import xyz.leutgeb.lorenz.atlas.typing.simple.types.BoolType;
import xyz.leutgeb.lorenz.atlas.typing.simple.types.Type;
import xyz.leutgeb.lorenz.atlas.unification.UnificationContext;
import xyz.leutgeb.lorenz.atlas.util.IntIdGenerator;

import java.io.PrintStream;
import java.util.Map;
import java.util.Stack;
import java.util.stream.Stream;

@Value
@EqualsAndHashCode(callSuper = true)
public class ArithmeticExpression extends Expression {

@NonNull Expression left;
@NonNull ArithmeticOperator operator;
@NonNull Expression right;

public ArithmeticExpression(
Source source,
@NonNull Expression left,
@NonNull ArithmeticOperator operator,
@NonNull Expression right) {
super(source);
this.left = left;
this.operator = operator;
this.right = right;
}

private ArithmeticExpression(
Source source, Expression left, ArithmeticOperator operator, Expression right, Type type) {
super(source);
this.left = left;
this.operator = operator;
this.right = right;
this.type = type;
}

@Override
public Stream<? extends Expression> getChildren() {
return Stream.of(left, right);
}

@Override
public Type inferInternal(UnificationContext context) throws TypeError {
var ty = context.fresh();
context.addEquivalenceIfNotEqual(right.infer(context), ty, source);
context.addEquivalenceIfNotEqual(left.infer(context), ty, source);
context
.getSignature(context.getFunctionInScope(), source)
.addConstraint(new TypeConstraint(TypeClass.NUM, ty));
return ty;
}

@Override
public Expression normalize(Stack<Normalization> context, IntIdGenerator idGenerator) {
// TODO(lorenzleutgeb): Only create new expression if necessary!
return new ArithmeticExpression(
Derived.anf(this),
left.normalize(context, idGenerator),
operator,
right.normalize(context, idGenerator));
}

@Override
public void printTo(PrintStream out, int indentation) {
left.printTo(out, indentation);
out.print(" ");
operator.printTo(out);
out.print(" ");
right.printTo(out, indentation);
}

@Override
public void printHaskellTo(PrintStream out, int indentation, String currentFunction) {
left.printHaskellTo(out, indentation, currentFunction);
out.print(" ");
operator.printHaskellTo(out);
out.print(" ");
right.printHaskellTo(out, indentation, currentFunction);
}

@Override
public void printJavaTo(PrintStream out, int indentation, String currentFunction) {
operator.printJavaTo(
((IdentifierExpression) left).getName(), ((IdentifierExpression) right).getName(), out);
}

@Override
public Expression unshare(IntIdGenerator idGenerator, boolean lazy) {
return this;
}

@Override
public boolean isImmediate() {
return false;
}

@Override
public Expression rename(Map<String, String> renaming) {
if (freeVariables().stream()
.map(IdentifierExpression::getName)
.anyMatch(renaming::containsKey)) {
return new ArithmeticExpression(
Derived.rename(this), left.rename(renaming), operator, right.rename(renaming), type);
}
return this;
}

@Override
public String toString() {
return left + " " + operator + " " + right;
}

@Override
public boolean isTerminal() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ public Stream<? extends Expression> getChildren() {

@Override
public Type inferInternal(UnificationContext context) throws TypeError {
// The next two lines hide polymorphism in favor of the "abstract base signature".
// context.add(right.infer(context), BaseType.INSTANCE);
// context.add(left.infer(context), BaseType.INSTANCE);

var ty = context.fresh();
context.addEquivalenceIfNotEqual(right.infer(context), ty, source);
context.addEquivalenceIfNotEqual(left.infer(context), ty, source);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package xyz.leutgeb.lorenz.atlas.ast.expressions;

import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.Value;
import xyz.leutgeb.lorenz.atlas.ast.sources.Source;
import xyz.leutgeb.lorenz.atlas.typing.simple.TypeClass;
import xyz.leutgeb.lorenz.atlas.typing.simple.TypeConstraint;
import xyz.leutgeb.lorenz.atlas.typing.simple.TypeError;
import xyz.leutgeb.lorenz.atlas.typing.simple.types.Type;
import xyz.leutgeb.lorenz.atlas.unification.UnificationContext;
import xyz.leutgeb.lorenz.atlas.util.IntIdGenerator;

import java.util.stream.Stream;

@Value
@EqualsAndHashCode(callSuper = true)
public class NumberExpression extends Expression {
@NonNull String number;

public NumberExpression(String number, Source source) {
super(source);
this.number = number;
}

@Override
protected Stream<? extends Expression> getChildren() {
return Stream.of();
}

@Override
protected Type inferInternal(UnificationContext context) throws TypeError {
var ty = context.fresh();
context
.getSignature(context.getFunctionInScope(), source)
.addConstraint(new TypeConstraint(TypeClass.NUM, ty));
return ty;
}

@Override
public Expression unshare(IntIdGenerator idGenerator, boolean lazy) {
return this;
}

@Override
public boolean isImmediate() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ public Expression visitComparison(SplayParser.ComparisonContext ctx) {
getSource(ctx), l, ComparisonOperator.fromToken(ctx.op().getText()), r);
}

@Override
public Expression visitArithExpression(SplayParser.ArithExpressionContext ctx) {
var l = ExpressionVisitor.this.visit(ctx.left);
var r = ExpressionVisitor.this.visit(ctx.right);
return new ArithmeticExpression(
getSource(ctx), l, ArithmeticOperator.fromToken(ctx.arithOp().getText()), r);
}

@Override
public Expression visitMatchExpression(SplayParser.MatchExpressionContext ctx) {
return new MatchTreeExpression(
Expand Down Expand Up @@ -154,6 +162,6 @@ public Expression visitParenthesizedExpression(SplayParser.ParenthesizedExpressi

@Override
public Expression visitConstant(SplayParser.ConstantContext ctx) {
throw new UnsupportedOperationException("literal numbers are not implemented");
return new NumberExpression(ctx.getText(), getSource(ctx));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public void run() {
stream.println();
stream.println("module " + lastModulePart + " where");
stream.println("import InterpreterPrelude (Tree(Node, Leaf))");
stream.println("import Data.Int (Int64)");
stream.println();
for (String imp : imports.get(e)) {
stream.println("import qualified " + imp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
class ModuleParser {
public static List<FunctionDefinition> parse(String s, String moduleName) {
try {
return parse(CharStreams.fromString(s), moduleName);
return parse(CharStreams.fromString(s, "inline"), moduleName);
// } catch (IOException e) {
// In this case we assume that something went fundamentally
// wrong when using a String as input. The caller probably
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ public String toString() {

sb.append(type.getFrom());

sb.append(" → ");
if (type.getFrom().size() > 0) {
sb.append(" → ");
}
sb.append(type.getTo());

if (annotation.isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@

import java.util.Set;
import lombok.Value;
import xyz.leutgeb.lorenz.atlas.typing.simple.types.Type;

@Value
public class TypeClass {
public static TypeClass EQ = new TypeClass("Eq", 1, emptySet());
public static TypeClass ORD = new TypeClass("Ord", 1, singleton(TypeClass.EQ));

public static TypeClass NUM = new TypeClass("Num", 1, emptySet());

String name;
int arity;

Expand Down

This file was deleted.

Loading

0 comments on commit c17d425

Please sign in to comment.