aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-12-23 12:05:34 +0000
committerMichael Williamson <mike@zwobble.org>2023-12-23 16:09:48 +0000
commit1886fc2b214bb2c5bfc4cb1ca3d49975c76da0d6 (patch)
tree23d4ee613b0b636b54be11ee147ea2ddf84aaf67 /src/main/java
parenta7c33eef7d2598d5636ff5bcde07da4f9c057184 (diff)
Parse constructed types
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedConstructedTypeNode.java12
-rw-r--r--src/main/java/org/shedlang/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java2
-rw-r--r--src/main/java/org/shedlang/compiler/parser/OperationParser.java7
-rw-r--r--src/main/java/org/shedlang/compiler/parser/Parser.java111
-rw-r--r--src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java15
-rw-r--r--src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java3
6 files changed, 128 insertions, 22 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedConstructedTypeNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedConstructedTypeNode.java
new file mode 100644
index 00000000..48cb1bf6
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedConstructedTypeNode.java
@@ -0,0 +1,12 @@
+package org.shedlang.compiler.ast.untyped;
+
+import org.shedlang.compiler.sources.Source;
+
+import java.util.List;
+
+public record UntypedConstructedTypeNode(
+ UntypedTypeLevelExpressionNode receiver,
+ List<UntypedTypeLevelExpressionNode> args,
+ Source source
+) implements UntypedTypeLevelExpressionNode {
+}
diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java
index 5af90cfa..7f677119 100644
--- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java
+++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java
@@ -1,4 +1,4 @@
package org.shedlang.compiler.ast.untyped;
-public sealed interface UntypedTypeLevelExpressionNode extends UntypedNode permits UntypedFunctionTypeNode, UntypedTupleTypeNode, UntypedTypeLevelReferenceNode {
+public sealed interface UntypedTypeLevelExpressionNode extends UntypedNode permits UntypedConstructedTypeNode, UntypedFunctionTypeNode, UntypedTupleTypeNode, UntypedTypeLevelReferenceNode {
}
diff --git a/src/main/java/org/shedlang/compiler/parser/OperationParser.java b/src/main/java/org/shedlang/compiler/parser/OperationParser.java
index 6f3e170e..9a4a25ea 100644
--- a/src/main/java/org/shedlang/compiler/parser/OperationParser.java
+++ b/src/main/java/org/shedlang/compiler/parser/OperationParser.java
@@ -1,12 +1,11 @@
package org.shedlang.compiler.parser;
-import org.shedlang.compiler.ast.untyped.UntypedExpressionNode;
import org.shedlang.compiler.tokeniser.TokenIterator;
import java.util.stream.Stream;
-public interface OperationParser {
- OperatorPrecedence precedence();
+public interface OperationParser<TOperatorPrecedence, TUntypedExpressionNode> {
+ TOperatorPrecedence precedence();
Stream<TokenType> operatorTokenTypes();
- UntypedExpressionNode parse(UntypedExpressionNode left, TokenIterator<TokenType> tokens);
+ TUntypedExpressionNode parse(TUntypedExpressionNode left, TokenIterator<TokenType> tokens);
}
diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java
index 753a6d75..3c91c561 100644
--- a/src/main/java/org/shedlang/compiler/parser/Parser.java
+++ b/src/main/java/org/shedlang/compiler/parser/Parser.java
@@ -24,7 +24,10 @@ public class Parser {
private Parser() {
}
- private static class BinaryOperationParser implements OperationParser {
+ private static class BinaryOperationParser implements OperationParser<
+ OperatorPrecedence,
+ UntypedExpressionNode
+ > {
private final TokenType operatorTokenType;
private final OperatorPrecedence precedence;
private final UntypedBinaryOperator operator;
@@ -188,7 +191,10 @@ public class Parser {
return new UntypedBreakNode(expression, source);
}
- private static class CallParser implements OperationParser {
+ private static class CallParser implements OperationParser<
+ OperatorPrecedence,
+ UntypedExpressionNode
+ > {
@Override
public OperatorPrecedence precedence() {
return OperatorPrecedence.CALL;
@@ -216,6 +222,39 @@ public class Parser {
}
}
+ private static class ConstructedTypeParser implements OperationParser<
+ TypeLevelOperatorPrecedence,
+ UntypedTypeLevelExpressionNode
+ > {
+ @Override
+ public TypeLevelOperatorPrecedence precedence() {
+ return TypeLevelOperatorPrecedence.CONSTRUCTED_TYPE;
+ }
+
+ @Override
+ public Stream<TokenType> operatorTokenTypes() {
+ return Stream.of(TokenType.SYMBOL_SQUARE_OPEN);
+ }
+
+ @Override
+ public UntypedTypeLevelExpressionNode parse(UntypedTypeLevelExpressionNode left, TokenIterator<TokenType> tokens) {
+ var start = left.source().start();
+
+ tokens.skip(TokenType.SYMBOL_SQUARE_OPEN);
+ var args = parseMany(
+ () -> tokens.isNext(TokenType.SYMBOL_SQUARE_CLOSE),
+ () -> parseTopLevelTypeLevelExpression(tokens),
+ () -> tokens.trySkip(TokenType.SYMBOL_COMMA)
+ );
+ tokens.skip(TokenType.SYMBOL_SQUARE_CLOSE);
+
+ var end = tokens.position();
+ var source = start.to(end);
+
+ return new UntypedConstructedTypeNode(left, args, source);
+ }
+ }
+
private static UntypedEffectDefinitionNode parseEffectDefinition(
TokenIterator<TokenType> tokens
) {
@@ -281,7 +320,7 @@ public class Parser {
return new UntypedFunctionTypeNode(params, Optional.empty(), returnType, source);
}
- private static final Map<TokenType, OperationParser> OPERATION_PARSERS = Stream.of(
+ private static final Map<TokenType, OperationParser<OperatorPrecedence, UntypedExpressionNode>> OPERATION_PARSERS = Stream.of(
new FieldAccessParser(),
new BinaryOperationParser(TokenType.SYMBOL_EQUALS_EQUALS, OperatorPrecedence.EQUALS, UntypedBinaryOperator.EQUALS),
new BinaryOperationParser(TokenType.SYMBOL_BANG_EQUALS, OperatorPrecedence.EQUALS, UntypedBinaryOperator.NOT_EQUAL),
@@ -354,7 +393,10 @@ public class Parser {
);
}
- private static class FieldAccessParser implements OperationParser {
+ private static class FieldAccessParser implements OperationParser<
+ OperatorPrecedence,
+ UntypedExpressionNode
+ > {
@Override
public OperatorPrecedence precedence() {
return OperatorPrecedence.CALL;
@@ -848,6 +890,22 @@ public class Parser {
};
}
+ static UntypedTypeLevelExpressionNode parsePrimaryTypeLevelExpression(TokenIterator<TokenType> tokens) {
+ return switch (tokens.peek().tokenType()) {
+ case IDENTIFIER ->
+ parseTypeLevelReference(tokens);
+
+ case KEYWORD_FN ->
+ parseFunctionType(tokens);
+
+ case SYMBOL_HASH_PAREN_OPEN ->
+ parseTupleType(tokens);
+
+ default ->
+ throw new UnexpectedTokenException("type-level expression", tokens.peek());
+ };
+ }
+
private static UntypedFunctionStatementNode parseResume(TokenIterator<TokenType> tokens) {
var start = tokens.position();
@@ -996,19 +1054,7 @@ public class Parser {
}
static UntypedTypeLevelExpressionNode parseTopLevelTypeLevelExpression(TokenIterator<TokenType> tokens) {
- return switch (tokens.peek().tokenType()) {
- case IDENTIFIER ->
- parseTypeLevelReference(tokens);
-
- case KEYWORD_FN ->
- parseFunctionType(tokens);
-
- case SYMBOL_HASH_PAREN_OPEN ->
- parseTupleType(tokens);
-
- default ->
- throw new UnexpectedTokenException("type-level expression", tokens.peek());
- };
+ return parseTypeLevelExpression(tokens, Optional.empty());
}
public static UntypedNamespaceNode parseNamespace(
@@ -1212,6 +1258,37 @@ public class Parser {
return new UntypedTupleTypeNode(elements, source);
}
+ private static final Map<TokenType, OperationParser<TypeLevelOperatorPrecedence, UntypedTypeLevelExpressionNode>> TYPE_LEVEL_OPERATION_PARSERS = Stream.of(
+ new ConstructedTypeParser()
+ )
+ .flatMap(parser ->
+ parser.operatorTokenTypes().map(tokenType -> Map.entry(tokenType, parser))
+ )
+ .collect(Collectors.toMap(
+ x -> x.getKey(),
+ x -> x.getValue()
+ ));
+
+ private static UntypedTypeLevelExpressionNode parseTypeLevelExpression(
+ TokenIterator<TokenType> tokens,
+ Optional<OperatorPrecedence> parentPrecedence
+ ) {
+ var left = parsePrimaryTypeLevelExpression(tokens);
+
+ while (true) {
+ var operationParser = TYPE_LEVEL_OPERATION_PARSERS.get(tokens.peek().tokenType());
+ if (
+ operationParser == null || (
+ parentPrecedence.isPresent() &&
+ operationParser.precedence().precedence() <= parentPrecedence.get().precedence()
+ )
+ ) {
+ return left;
+ }
+ left = operationParser.parse(left, tokens);
+ }
+ }
+
private static Optional<List<UntypedTypeLevelParamNode>> parseTypeLevelParamsOptional(
TokenIterator<TokenType> tokens
) {
diff --git a/src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java b/src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java
new file mode 100644
index 00000000..2068b2ad
--- /dev/null
+++ b/src/main/java/org/shedlang/compiler/parser/TypeLevelOperatorPrecedence.java
@@ -0,0 +1,15 @@
+package org.shedlang.compiler.parser;
+
+public enum TypeLevelOperatorPrecedence {
+ CONSTRUCTED_TYPE(1);
+
+ private final int precedence;
+
+ TypeLevelOperatorPrecedence(int precedence) {
+ this.precedence = precedence;
+ }
+
+ public int precedence() {
+ return precedence;
+ }
+}
diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
index f083913f..b789e888 100644
--- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java
@@ -1528,6 +1528,9 @@ public class TypeChecker {
TypeCheckerContext context
) {
return switch (untyped) {
+ case UntypedConstructedTypeNode constructedType ->
+ throw new UnsupportedOperationException("TODO");
+
case UntypedFunctionTypeNode functionType -> {
var typedFunctionTypeNode = typeCheckFunctionType(functionType, context);