From 436f43fa2667c77ef8a7d05bb5b8001c17c7822b Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 17 Jan 2025 23:32:18 +0000 Subject: Add support for native functions --- .../ast/typed/TypedFunctionSignatureNode.java | 9 +++- .../typed/TypedNativeFunctionDeclarationNode.java | 11 +++++ .../org/shedlang/compiler/shid/ShidCodeGen.java | 6 +++ .../org/shedlang/compiler/shid/ShidSerializer.java | 16 +++++-- .../instructions/ShidDeclareNativeFunction.java | 42 +++++++++++++++-- .../shedlang/compiler/shidtopatio/ShidToPatio.java | 27 +++++++++-- .../compiler/shidtopatio/ShidToPatioClosures.java | 54 +++++++++++++++++++++- .../compiler/shidtopatio/ShidToPatioFunctions.java | 24 ++++++++++ 8 files changed, 175 insertions(+), 14 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionSignatureNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionSignatureNode.java index 2e535a7d..839cbcf0 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionSignatureNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedFunctionSignatureNode.java @@ -63,9 +63,16 @@ public record TypedFunctionSignatureNode( } public Builder addNamedParam(String name, TypedTypeLevelExpressionNode type) { + return addNamedParam(name, Optional.of(type)); + } + + public Builder addNamedParam( + String name, + Optional> type + ) { return new Builder( this.positionalParams, - this.namedParams.plus(new TypedParamNode(name, Optional.of(type), Sources.NULL)), + this.namedParams.plus(new TypedParamNode(name, type, Sources.NULL)), this.effect, this.returnType ); diff --git a/src/main/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNode.java b/src/main/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNode.java index e22bc311..f94ef1fc 100644 --- a/src/main/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNode.java +++ b/src/main/java/org/shedlang/compiler/ast/typed/TypedNativeFunctionDeclarationNode.java @@ -69,6 +69,17 @@ public record TypedNativeFunctionDeclarationNode( ); } + public TypedNativeFunctionDeclarationNode.Builder addNamedParam( + String name, + Optional> type + ) { + return new TypedNativeFunctionDeclarationNode.Builder( + this.name, + this.signature.addNamedParam(name, type), + this.type + ); + } + public TypedNativeFunctionDeclarationNode.Builder withEffect(TypedTypeLevelExpressionNode effect) { return new TypedNativeFunctionDeclarationNode.Builder( this.name, diff --git a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java index f6830ae5..350ed118 100644 --- a/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java +++ b/src/main/java/org/shedlang/compiler/shid/ShidCodeGen.java @@ -631,6 +631,12 @@ public class ShidCodeGen { context = context.addInstruction(new ShidDeclareNativeFunction( context.namespaceName(), node.name(), + node.signature().params().positional().stream() + .map(param -> new ShidParam(param.name(), param.source())) + .toList(), + node.signature().params().named().stream() + .map(param -> new ShidParam(param.name(), param.source())) + .toList(), node.source() )); diff --git a/src/main/java/org/shedlang/compiler/shid/ShidSerializer.java b/src/main/java/org/shedlang/compiler/shid/ShidSerializer.java index 54cd53e5..590c3d39 100644 --- a/src/main/java/org/shedlang/compiler/shid/ShidSerializer.java +++ b/src/main/java/org/shedlang/compiler/shid/ShidSerializer.java @@ -2,6 +2,7 @@ package org.shedlang.compiler.shid; import org.shedlang.compiler.shid.instructions.*; import org.shedlang.compiler.treetext.Tree; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.SimpleStructType; import org.shedlang.compiler.types.UserDefinedEffect; @@ -76,7 +77,10 @@ public class ShidSerializer { case ShidDeclareNativeFunction declareNativeFunction -> treeListIndented( treeIdentifier("declare-native-function"), - treeNamed("name", treeString(declareNativeFunction.name())) + treeNamed("namespace-name", namespaceNameToTree(declareNativeFunction.namespaceName())), + treeNamed("name", treeString(declareNativeFunction.name())), + positionalParamsToTree(declareNativeFunction.positionalParams()), + namedParamsToTree(declareNativeFunction.namedParams()) ); case ShidDefineEffect defineEffectInstruction -> @@ -143,7 +147,7 @@ public class ShidSerializer { case ShidFieldLoad.Receiver.Namespace namespace -> treeList( treeIdentifier("namespace"), - treeString(namespace.name().toString()) + namespaceNameToTree(namespace.name()) ); case ShidFieldLoad.Receiver.Struct struct -> @@ -222,14 +226,14 @@ public class ShidSerializer { case ShidNamespaceFieldStore namespaceFieldStore -> treeList( treeIdentifier("namespace-field-store"), - treeString(namespaceFieldStore.namespaceName().toString()), + namespaceNameToTree(namespaceFieldStore.namespaceName()), treeString(namespaceFieldStore.fieldName()) ); case ShidNamespaceImport namespaceImport -> treeList( treeIdentifier("namespace-import"), - treeString(namespaceImport.namespaceName().toString()) + namespaceNameToTree(namespaceImport.namespaceName()) ); case ShidPushBool pushBoolInstruction -> @@ -320,6 +324,10 @@ public class ShidSerializer { }; } + private static Tree namespaceNameToTree(NamespaceName namespaceName) { + return treeString(namespaceName.toString()); + } + private static Tree positionalParamsToTree(List positionalParams) { return treeNamed("positional-params", treeList( positionalParams.stream() diff --git a/src/main/java/org/shedlang/compiler/shid/instructions/ShidDeclareNativeFunction.java b/src/main/java/org/shedlang/compiler/shid/instructions/ShidDeclareNativeFunction.java index 9f88ca5f..56b7e287 100644 --- a/src/main/java/org/shedlang/compiler/shid/instructions/ShidDeclareNativeFunction.java +++ b/src/main/java/org/shedlang/compiler/shid/instructions/ShidDeclareNativeFunction.java @@ -1,8 +1,12 @@ package org.shedlang.compiler.shid.instructions; +import org.pcollections.PVector; import org.shedlang.compiler.sources.Source; import org.shedlang.compiler.sources.Sources; import org.shedlang.compiler.types.NamespaceName; +import org.shedlang.compiler.util.P; + +import java.util.List; /** * Push a native function value onto the temporary value stack with the given @@ -11,6 +15,8 @@ import org.shedlang.compiler.types.NamespaceName; public record ShidDeclareNativeFunction( NamespaceName namespaceName, String name, + List positionalParams, + List namedParams, Source source ) implements ShidInstruction { @Override @@ -21,18 +27,24 @@ public record ShidDeclareNativeFunction( public static Builder builder() { return new Builder( NamespaceName.of(), - "f" + "f", + P.vector(), + P.vector() ); } public record Builder( NamespaceName namespaceName, - String name + String name, + PVector positionalParams, + PVector namedParams ) { public ShidDeclareNativeFunction build() { return new ShidDeclareNativeFunction( this.namespaceName, this.name, + this.positionalParams, + this.namedParams, Sources.NULL ); } @@ -40,14 +52,36 @@ public record ShidDeclareNativeFunction( public Builder withNamespaceName(NamespaceName namespaceName) { return new Builder( namespaceName, - this.name + this.name, + this.positionalParams, + this.namedParams ); } public Builder withName(String name) { return new Builder( this.namespaceName, - name + name, + this.positionalParams, + this.namedParams + ); + } + + public Builder addPositionalParam(String name) { + return new Builder( + this.namespaceName, + this.name, + this.positionalParams.plus(new ShidParam(name, Sources.NULL)), + this.namedParams + ); + } + + public Builder addNamedParam(String name) { + return new Builder( + this.namespaceName, + this.name, + this.positionalParams, + this.namedParams.plus(new ShidParam(name, Sources.NULL)) ); } } diff --git a/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatio.java b/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatio.java index 11fcdee8..b039789a 100644 --- a/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatio.java +++ b/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatio.java @@ -244,6 +244,30 @@ public class ShidToPatio { yield context; } + case ShidDeclareNativeFunction declareNativeFunction -> { + var destinationResult = context.allocateVal( + ShidToPatioLocalSpace.CLOSURE, + declareNativeFunction.name(), + ShidToPatioTypes.VALUE_TYPE + ); + var destination = destinationResult.value(); + context = destinationResult.context(); + + context = ShidToPatioFunctions.createNative( + destination, + declareNativeFunction.namespaceName(), + declareNativeFunction.name(), + declareNativeFunction.positionalParams(), + declareNativeFunction.namedParams(), + declareNativeFunction.source(), + context + ); + + context = context.temporaryPush(destination); + + yield context; + } + case ShidDefineFunction defineFunction -> { var destinationResult = context.allocateVal( ShidToPatioLocalSpace.CLOSURE, @@ -595,9 +619,6 @@ public class ShidToPatio { yield context; } - case ShidDeclareNativeFunction declareNativeFunction -> - throw new UnsupportedOperationException("TODO"); - case ShidPushBool pushBool -> pushValue(pushBool.value() ? 1 : 0, pushBool.source(), context); diff --git a/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioClosures.java b/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioClosures.java index 624a2787..f93b2844 100644 --- a/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioClosures.java +++ b/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioClosures.java @@ -2,6 +2,8 @@ package org.shedlang.compiler.shidtopatio; import org.shedlang.compiler.ast.typed.FreeVariable; import org.shedlang.compiler.ast.typed.FreeVariables; +import org.shedlang.compiler.patio.PatioFunctionDeclaration; +import org.shedlang.compiler.patio.PatioLocal; import org.shedlang.compiler.patio.PatioVisibility; import org.shedlang.compiler.patio.instructions.*; import org.shedlang.compiler.patio.operands.PatioFunctionPtrConst; @@ -13,6 +15,7 @@ import org.shedlang.compiler.patio.types.PatioType; import org.shedlang.compiler.patio.types.PatioTypes; import org.shedlang.compiler.shid.instructions.ShidParam; import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.util.P; import java.util.ArrayList; @@ -99,8 +102,7 @@ class ShidToPatioClosures { List namedParams, ShidToPatioContext bodyContext ) { - var orderedNamedParams = sortedBy(namedParams, param -> param.name()); - var shidParams = Stream.concat(positionalParams.stream(), orderedNamedParams.stream()).toList(); + var shidParams = generateShidParamList(positionalParams, namedParams); for (var shidParam : shidParams) { bodyContext = bodyContext.defineShidParam(shidParam.name()); @@ -109,6 +111,14 @@ class ShidToPatioClosures { return bodyContext; } + private static List generateShidParamList( + List positionalParams, + List namedParams + ) { + var orderedNamedParams = sortedBy(namedParams, param -> param.name()); + return Stream.concat(positionalParams.stream(), orderedNamedParams.stream()).toList(); + } + static ShidToPatioContext create( PatioLocalRef destination, ShidToPatioCompilationUnitElementSpace functionElementSpace, @@ -170,6 +180,46 @@ class ShidToPatioClosures { return context; } + public static ShidToPatioContext createNative( + PatioLocalRef destination, + NamespaceName namespaceName, + String name, + List positionalParams, + List namedParams, + ClosureRuntimeType closureRuntimeType, + Source source, + ShidToPatioContext context + ) { + var fullName = String.format( + "shed__runtime__namespace__%s__%s", + String.join("__", namespaceName.parts()), + name + ); + + context = context.addCompilationUnitElement(new PatioFunctionDeclaration( + fullName, + generateShidParamList(positionalParams, namedParams).stream() + .map(param -> PatioLocal.param(param.name(), ShidToPatioTypes.VALUE_TYPE)) + .toList(), + ShidToPatioTypes.VALUE_TYPE, + source + )); + + context = alloc( + destination, + name, + fullName, + closureRuntimeType, + (closurePointer, storeContext) -> storeContext, + FreeVariables.empty(), + source, + context + ); + + return context; + } + + static ShidToPatioContext alloc( PatioLocalRef destination, String name, diff --git a/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioFunctions.java b/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioFunctions.java index c4edd762..105ca4e9 100644 --- a/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioFunctions.java +++ b/src/main/java/org/shedlang/compiler/shidtopatio/ShidToPatioFunctions.java @@ -6,6 +6,7 @@ import org.shedlang.compiler.patio.types.PatioDataLayout; import org.shedlang.compiler.patio.types.PatioDataLayouts; import org.shedlang.compiler.shid.instructions.ShidParam; import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.types.NamespaceName; import java.util.List; import java.util.function.Function; @@ -53,4 +54,27 @@ public class ShidToPatioFunctions { context ); } + + public static ShidToPatioContext createNative( + PatioLocalRef destination, + NamespaceName namespaceName, + String name, + List positionalParams, + List namedParams, + Source source, + ShidToPatioContext context + ) { + var functionRuntimeType = functionRuntimeType(FreeVariables.empty(), context); + + return ShidToPatioClosures.createNative( + destination, + namespaceName, + name, + positionalParams, + namedParams, + functionRuntimeType, + source, + context + ); + } } -- cgit v1.2.3