Skip to content

Commit

Permalink
feat: Add compiling VariableStatement
Browse files Browse the repository at this point in the history
  • Loading branch information
furesoft committed Dec 26, 2024
1 parent 6bdec5b commit 1838f95
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 8 deletions.
6 changes: 6 additions & 0 deletions NewSource/Socordia.CodeAnalysis/AST/EmptyNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Socordia.CodeAnalysis.AST;

public class EmptyNode : AstNode
{

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Socordia.CodeAnalysis.AST.Statements;
using Socordia.CodeAnalysis.AST.TypeNames;

namespace Socordia.CodeAnalysis.AST.Statements;

public class VariableStatement : AstNode
{
Expand All @@ -13,6 +15,6 @@ public VariableStatement(string name, AstNode? type, AstNode initializer, bool i
public string Name => Properties.GetOrThrow<string>(nameof(Name));
public bool IsMutable => Properties.GetOrDefault<bool>(nameof(IsMutable));

public AstNode? Type => Children.First;
public TypeName? Type => (TypeName)Children.First;
public AstNode Initializer => Children.Last;
}
3 changes: 3 additions & 0 deletions NewSource/Socordia.CodeAnalysis/AST/TypeNames/NoTypeName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Socordia.CodeAnalysis.AST.TypeNames;

public class NoTypeName : TypeName;
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
14 changes: 14 additions & 0 deletions NewSource/SocordiaC/Compilation/Body/BodyCompilation.cs
Original file line number Diff line number Diff line change
@@ -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<BodyCompilation, AstNode> Listener =
CompositeListener<BodyCompilation, AstNode>.Build()
.With(new VariableDeclarationListener())
.ToListener();
}
Original file line number Diff line number Diff line change
@@ -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<BodyCompilation, AstNode, VariableStatement>
{
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);
}
}
33 changes: 33 additions & 0 deletions NewSource/SocordiaC/Compilation/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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()
};
}
}
7 changes: 7 additions & 0 deletions NewSource/SocordiaC/Stages/CompileFunctionsStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using DistIL.IR.Utils;
using Flo;
using SocordiaC.Compilation;
using SocordiaC.Compilation.Body;

namespace SocordiaC.Stages;

Expand All @@ -13,11 +14,17 @@ public async Task<Driver> HandleAsync(Driver context, Func<Driver, Task<Driver>>
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);
}
Expand Down
2 changes: 1 addition & 1 deletion NewSource/SocordiaC/compilation.sc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module TestSuite;

func main() -> none {

let myFlag = true;
}

private func test(hello: i32, flag: bool) -> i32
Expand Down

0 comments on commit 1838f95

Please sign in to comment.