diff --git a/NewSource/Socordia.CodeAnalysis/AST/EmptyNode.cs b/NewSource/Socordia.CodeAnalysis/AST/EmptyNode.cs new file mode 100644 index 00000000..cb842342 --- /dev/null +++ b/NewSource/Socordia.CodeAnalysis/AST/EmptyNode.cs @@ -0,0 +1,6 @@ +namespace Socordia.CodeAnalysis.AST; + +public class EmptyNode : AstNode +{ + +} \ No newline at end of file diff --git a/NewSource/Socordia.CodeAnalysis/AST/Statements/VariableStatement.cs b/NewSource/Socordia.CodeAnalysis/AST/Statements/VariableStatement.cs index 2077149f..ca0edddf 100644 --- a/NewSource/Socordia.CodeAnalysis/AST/Statements/VariableStatement.cs +++ b/NewSource/Socordia.CodeAnalysis/AST/Statements/VariableStatement.cs @@ -1,4 +1,6 @@ -namespace Socordia.CodeAnalysis.AST.Statements; +using Socordia.CodeAnalysis.AST.TypeNames; + +namespace Socordia.CodeAnalysis.AST.Statements; public class VariableStatement : AstNode { @@ -13,6 +15,6 @@ public VariableStatement(string name, AstNode? type, AstNode initializer, bool i public string Name => Properties.GetOrThrow(nameof(Name)); public bool IsMutable => Properties.GetOrDefault(nameof(IsMutable)); - public AstNode? Type => Children.First; + public TypeName? Type => (TypeName)Children.First; public AstNode Initializer => Children.Last; } \ No newline at end of file diff --git a/NewSource/Socordia.CodeAnalysis/AST/TypeNames/NoTypeName.cs b/NewSource/Socordia.CodeAnalysis/AST/TypeNames/NoTypeName.cs new file mode 100644 index 00000000..2250f175 --- /dev/null +++ b/NewSource/Socordia.CodeAnalysis/AST/TypeNames/NoTypeName.cs @@ -0,0 +1,3 @@ +namespace Socordia.CodeAnalysis.AST.TypeNames; + +public class NoTypeName : TypeName; \ No newline at end of file diff --git a/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/Statements/VariableStatementParser.cs b/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/Statements/VariableStatementParser.cs index 1666aea8..7bafa12e 100644 --- a/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/Statements/VariableStatementParser.cs +++ b/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/Statements/VariableStatementParser.cs @@ -11,7 +11,7 @@ public static AstNode Parse(TokenIterator iterator, Parser parser) var keywordToken = iterator.Prev; var isMutable = false; - TypeName? type = null; + TypeName? type = new NoTypeName(); Token mutableToken = null; @@ -30,16 +30,16 @@ public static AstNode Parse(TokenIterator iterator, Parser parser) type = TypeNameParser.Parse(parser); } - AstNode initilizer = null; + AstNode initializer = new EmptyNode(); if (iterator.Current.Type == TokenType.EqualsToken) { iterator.NextToken(); - initilizer = Expression.Parse(parser); + initializer = Expression.Parse(parser); } iterator.Match(TokenType.Semicolon); - return new VariableStatement(nameToken.Text, type, initilizer, isMutable); + return new VariableStatement(nameToken.Text, type, initializer, isMutable); } } \ No newline at end of file diff --git a/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/TypeNameParser.cs b/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/TypeNameParser.cs index 5c176769..ef683baf 100644 --- a/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/TypeNameParser.cs +++ b/NewSource/Socordia.CodeAnalysis/Parsing/ParsePoints/TypeNameParser.cs @@ -72,7 +72,7 @@ public static TypeName Parse(Parser parser) parser.AddError("Expected Identifier, TupleType or Function-Signature as TypeLiteral, but got " + TokenIterator.GetTokenRepresentation(iterator.Current.Type)); - typeNode = null; + typeNode = new NoTypeName(); iterator.NextToken(); } diff --git a/NewSource/SocordiaC/Compilation/Body/BodyCompilation.cs b/NewSource/SocordiaC/Compilation/Body/BodyCompilation.cs new file mode 100644 index 00000000..c7042b97 --- /dev/null +++ b/NewSource/SocordiaC/Compilation/Body/BodyCompilation.cs @@ -0,0 +1,14 @@ +using DistIL.AsmIO; +using DistIL.IR.Utils; +using MrKWatkins.Ast.Listening; +using Socordia.CodeAnalysis.AST; + +namespace SocordiaC.Compilation.Body; + +public record BodyCompilation(Driver Driver, MethodDef Method, IRBuilder Builder) +{ + public static CompositeListener Listener = + CompositeListener.Build() + .With(new VariableDeclarationListener()) + .ToListener(); +} \ No newline at end of file diff --git a/NewSource/SocordiaC/Compilation/Body/VariableDeclarationListener.cs b/NewSource/SocordiaC/Compilation/Body/VariableDeclarationListener.cs new file mode 100644 index 00000000..54c54214 --- /dev/null +++ b/NewSource/SocordiaC/Compilation/Body/VariableDeclarationListener.cs @@ -0,0 +1,33 @@ +using DistIL.AsmIO; +using MrKWatkins.Ast.Listening; +using Socordia.CodeAnalysis.AST; +using Socordia.CodeAnalysis.AST.Statements; +using Socordia.CodeAnalysis.AST.TypeNames; + +namespace SocordiaC.Compilation.Body; + +public class VariableDeclarationListener : Listener +{ + protected override void ListenToNode(BodyCompilation context, VariableStatement node) + { + var value = Utils.CreateValue(node.Initializer); + + TypeDesc type; + if (node.Type is not NoTypeName) + { + type = Utils.GetTypeFromNode(node.Type, context.Driver.Compilation.Module)!; + if (type != value.ResultType) + { + node.Type.AddError("Type mismatch"); + } + } + else + { + type = value.ResultType; + } + + var slot = context.Method.Body!.CreateVar(type!, node.Name); + + context.Builder.CreateStore(slot, value); + } +} \ No newline at end of file diff --git a/NewSource/SocordiaC/Compilation/Utils.cs b/NewSource/SocordiaC/Compilation/Utils.cs index a09463ae..0e7d4e34 100644 --- a/NewSource/SocordiaC/Compilation/Utils.cs +++ b/NewSource/SocordiaC/Compilation/Utils.cs @@ -2,6 +2,7 @@ using DistIL.IR; using Socordia.CodeAnalysis.AST; using Socordia.CodeAnalysis.AST.Declarations; +using Socordia.CodeAnalysis.AST.Literals; using Socordia.CodeAnalysis.AST.TypeNames; namespace SocordiaC.Compilation; @@ -81,6 +82,11 @@ public static string ToPascalCase(string name) public static TypeDefOrSpec? GetTypeFromNode(TypeName node, ModuleDef module) { + if (node is NoTypeName) + { + return null; + } + if (node is QualifiedTypeName qname) { if (qname.Type is SimpleTypeName simple) @@ -97,4 +103,31 @@ public static string ToPascalCase(string name) throw new Exception("cannot get type from node"); } + + public static Value CreateValue(AstNode valueNode) + { + return valueNode switch + { + LiteralNode literal => CreateLiteral(literal.Value), + _ => throw new NotImplementedException() + }; + } + + private static Value CreateLiteral(object literalValue) + { + return literalValue switch + { + bool b => ConstInt.Create(PrimType.Bool, b ? 1 : 0), + byte by => ConstInt.CreateI(by), + short s => ConstInt.CreateI(s), + int i => ConstInt.CreateI(i), + long l => ConstInt.CreateL(l), + float f => ConstFloat.CreateD(f), + double d => ConstFloat.CreateD(d), + string str => ConstString.Create(str), + char c => ConstInt.CreateI(c), + null => ConstNull.Create(), + _ => throw new NotImplementedException() + }; + } } \ No newline at end of file diff --git a/NewSource/SocordiaC/Stages/CompileFunctionsStage.cs b/NewSource/SocordiaC/Stages/CompileFunctionsStage.cs index 072c9519..66c1fde7 100644 --- a/NewSource/SocordiaC/Stages/CompileFunctionsStage.cs +++ b/NewSource/SocordiaC/Stages/CompileFunctionsStage.cs @@ -3,6 +3,7 @@ using DistIL.IR.Utils; using Flo; using SocordiaC.Compilation; +using SocordiaC.Compilation.Body; namespace SocordiaC.Stages; @@ -13,11 +14,17 @@ public async Task HandleAsync(Driver context, Func> foreach (var (node, def) in Mappings.Functions) { var builder = new IRBuilder(def.Body!.CreateBlock()); + var bodyCompilation = new BodyCompilation(context, def, builder); if (!node.Children[1].HasChildren) { builder.Emit(new ReturnInst()); } + else + { + BodyCompilation.Listener.Listen(bodyCompilation, node); + builder.Emit(new ReturnInst()); + } def.ILBody = ILGenerator.GenerateCode(def.Body); } diff --git a/NewSource/SocordiaC/compilation.sc b/NewSource/SocordiaC/compilation.sc index 59f9fc8d..2e3d4fa2 100644 --- a/NewSource/SocordiaC/compilation.sc +++ b/NewSource/SocordiaC/compilation.sc @@ -1,7 +1,7 @@ module TestSuite; func main() -> none { - + let myFlag = true; } private func test(hello: i32, flag: bool) -> i32