...
This commit is contained in:
@@ -467,7 +467,7 @@ public class QBEGenerator
|
|||||||
|
|
||||||
private void EmitBlock(BlockNode block, Scope? scope = null)
|
private void EmitBlock(BlockNode block, Scope? scope = null)
|
||||||
{
|
{
|
||||||
scope ??= Scope.SubScope();
|
scope ??= new Scope();
|
||||||
_scopes.Push(scope);
|
_scopes.Push(scope);
|
||||||
|
|
||||||
foreach (var statement in block.Statements)
|
foreach (var statement in block.Statements)
|
||||||
@@ -1295,12 +1295,6 @@ public class QBEGenerator
|
|||||||
return new NubStructType(definition.Module, definition.Name, fieldTypes, functionTypes);
|
return new NubStructType(definition.Module, definition.Name, fieldTypes, functionTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubFuncType TypeOfFunc(FuncSignatureNode signature)
|
|
||||||
{
|
|
||||||
var parameters = signature.Parameters.Select(x => x.Type).ToList();
|
|
||||||
return new NubFuncType(parameters, signature.ReturnType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string TmpName()
|
private string TmpName()
|
||||||
{
|
{
|
||||||
return $"%.t{++_tmpIndex}";
|
return $"%.t{++_tmpIndex}";
|
||||||
@@ -1342,16 +1336,10 @@ public class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo(nub31): Parent is not used when getting variables and deferred statements
|
public class Scope
|
||||||
public class Scope(Scope? parent = null)
|
|
||||||
{
|
{
|
||||||
public readonly Stack<StatementNode> DeferredStatements = [];
|
public readonly Stack<StatementNode> DeferredStatements = [];
|
||||||
public readonly Stack<Variable> Variables = [];
|
public readonly Stack<Variable> Variables = [];
|
||||||
|
|
||||||
public Scope SubScope()
|
|
||||||
{
|
|
||||||
return new Scope(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Variable(string Name, NubType Type);
|
public record Variable(string Name, NubType Type);
|
||||||
|
|||||||
@@ -39,5 +39,3 @@ public record ModuleStruct(bool Exported, string Name, List<ModuleStructField> F
|
|||||||
public record ModuleFunctionParameter(string Name, TypeSyntax Type);
|
public record ModuleFunctionParameter(string Name, TypeSyntax Type);
|
||||||
|
|
||||||
public record ModuleFunction(bool Exported, string Name, string? ExternSymbol, List<ModuleFunctionParameter> Parameters, TypeSyntax ReturnType);
|
public record ModuleFunction(bool Exported, string Name, string? ExternSymbol, List<ModuleFunctionParameter> Parameters, TypeSyntax ReturnType);
|
||||||
|
|
||||||
public record ModuleTemplateStruct(bool Exported, string? Name);
|
|
||||||
@@ -70,19 +70,18 @@ public sealed class TypeChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Scope BeginScope(bool root)
|
private void BeginScope(bool root)
|
||||||
{
|
{
|
||||||
var scope = root
|
var scope = root
|
||||||
? _globalScope.SubScope()
|
? _globalScope.SubScope()
|
||||||
: _scopes.Peek().SubScope();
|
: _scopes.Peek().SubScope();
|
||||||
|
|
||||||
_scopes.Push(scope);
|
_scopes.Push(scope);
|
||||||
return scope;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Scope EndScope()
|
private void EndScope()
|
||||||
{
|
{
|
||||||
return _scopes.Pop();
|
_scopes.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructNode CheckStructDefinition(StructSyntax node)
|
private StructNode CheckStructDefinition(StructSyntax node)
|
||||||
@@ -841,13 +840,24 @@ public sealed class TypeChecker
|
|||||||
|
|
||||||
private bool AlwaysReturns(StatementNode statement)
|
private bool AlwaysReturns(StatementNode statement)
|
||||||
{
|
{
|
||||||
return statement switch
|
switch (statement)
|
||||||
{
|
{
|
||||||
ReturnNode => true,
|
case ReturnNode:
|
||||||
BlockNode block => block.Statements.Count != 0 && AlwaysReturns(block.Statements.Last()),
|
return true;
|
||||||
IfNode ifNode => AlwaysReturns(ifNode.Body) && ifNode.Else.TryGetValue(out var elseStatement) ? elseStatement.Match(AlwaysReturns, AlwaysReturns) : true,
|
case BlockNode block:
|
||||||
_ => false
|
return block.Statements.Count != 0 && AlwaysReturns(block.Statements.Last());
|
||||||
};
|
case IfNode ifNode:
|
||||||
|
{
|
||||||
|
if (!AlwaysReturns(ifNode.Body))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !ifNode.Else.TryGetValue(out var elseStatement) || elseStatement.Match(AlwaysReturns, AlwaysReturns);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubType ResolveType(TypeSyntax type)
|
private NubType ResolveType(TypeSyntax type)
|
||||||
|
|||||||
@@ -11,49 +11,49 @@ struct Human
|
|||||||
|
|
||||||
extern "main" func main(args: []cstring): i64
|
extern "main" func main(args: []cstring): i64
|
||||||
{
|
{
|
||||||
// let x: ref<Human> = {}
|
let x: ref<Human> = {}
|
||||||
|
|
||||||
// test(x)
|
test(x)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// func test(x: ref<Human>)
|
func test(x: ref<Human>)
|
||||||
// {
|
{
|
||||||
|
|
||||||
// }
|
}
|
||||||
|
|
||||||
// struct ref<T>
|
struct ref<T>
|
||||||
// {
|
{
|
||||||
// value: ^T
|
value: ^T
|
||||||
// count: ^u64
|
count: ^u64
|
||||||
|
|
||||||
// @oncreate
|
@oncreate
|
||||||
// func on_create()
|
func on_create()
|
||||||
// {
|
{
|
||||||
// puts("on_create")
|
puts("on_create")
|
||||||
// this.value = @interpret(^T, malloc(@size(T)))
|
this.value = @interpret(^T, malloc(@size(T)))
|
||||||
// this.count = @interpret(^u64, malloc(@size(u64)))
|
this.count = @interpret(^u64, malloc(@size(u64)))
|
||||||
// this.count^ = 1
|
this.count^ = 1
|
||||||
// }
|
}
|
||||||
|
|
||||||
// @oncopy
|
@oncopy
|
||||||
// func on_copy()
|
func on_copy()
|
||||||
// {
|
{
|
||||||
// puts("on_copy")
|
puts("on_copy")
|
||||||
// this.count^ = this.count^ + 1
|
this.count^ = this.count^ + 1
|
||||||
// }
|
}
|
||||||
|
|
||||||
// @ondestroy
|
@ondestroy
|
||||||
// func on_destroy()
|
func on_destroy()
|
||||||
// {
|
{
|
||||||
// puts("on_destroy")
|
puts("on_destroy")
|
||||||
// this.count^ = this.count^ - 1
|
this.count^ = this.count^ - 1
|
||||||
// if this.count^ <= 0
|
if this.count^ <= 0
|
||||||
// {
|
{
|
||||||
// puts("free")
|
puts("free")
|
||||||
// free(@interpret(^void, this.value))
|
free(@interpret(^void, this.value))
|
||||||
// free(@interpret(^void, this.count))
|
free(@interpret(^void, this.count))
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
Reference in New Issue
Block a user