extern
This commit is contained in:
@@ -46,7 +46,9 @@ public class Generator
|
|||||||
if (!moduleGraph.TryResolveIdentifier(function.Module, function.Name.Ident, true, out var info))
|
if (!moduleGraph.TryResolveIdentifier(function.Module, function.Name.Ident, true, out var info))
|
||||||
throw new UnreachableException($"Module graph does not have info about the function {function.Module}::{function.Name.Ident}. This should have been caught earlier");
|
throw new UnreachableException($"Module graph does not have info about the function {function.Module}::{function.Name.Ident}. This should have been caught earlier");
|
||||||
|
|
||||||
if (info.Kind == Module.DefinitionKind.Internal)
|
if (info.Source == Module.DefinitionSource.Imported || info.Extern)
|
||||||
|
writer.Write("extern ");
|
||||||
|
else if (info.Source == Module.DefinitionSource.Internal && !info.Extern && !info.Exported)
|
||||||
writer.Write("static ");
|
writer.Write("static ");
|
||||||
|
|
||||||
var parameters = function.Parameters.Select(x => CType(x.Type, x.Name.Ident));
|
var parameters = function.Parameters.Select(x => CType(x.Type, x.Name.Ident));
|
||||||
@@ -85,15 +87,10 @@ public class Generator
|
|||||||
{
|
{
|
||||||
foreach (var (name, info) in module.GetIdentifiers())
|
foreach (var (name, info) in module.GetIdentifiers())
|
||||||
{
|
{
|
||||||
switch (info.Kind)
|
if (info.Source == Module.DefinitionSource.Imported || info.Extern)
|
||||||
{
|
|
||||||
case Module.DefinitionKind.External:
|
|
||||||
writer.Write("extern ");
|
writer.Write("extern ");
|
||||||
break;
|
else if (info.Source == Module.DefinitionSource.Internal && !info.Extern && !info.Exported)
|
||||||
case Module.DefinitionKind.Internal:
|
|
||||||
writer.Write("static ");
|
writer.Write("static ");
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.Type is NubTypeFunc fn)
|
if (info.Type is NubTypeFunc fn)
|
||||||
writer.WriteLine($"{CType(fn.ReturnType, info.MangledName)}({string.Join(", ", fn.Parameters.Select(p => CType(p)))});");
|
writer.WriteLine($"{CType(fn.ReturnType, info.MangledName)}({string.Join(", ", fn.Parameters.Select(p => CType(p)))});");
|
||||||
@@ -122,7 +119,7 @@ public class Generator
|
|||||||
writer.WriteLine("{");
|
writer.WriteLine("{");
|
||||||
using (writer.Indent())
|
using (writer.Indent())
|
||||||
{
|
{
|
||||||
writer.WriteLine("const char *data;");
|
writer.WriteLine("char *data;");
|
||||||
writer.WriteLine("size_t length;");
|
writer.WriteLine("size_t length;");
|
||||||
}
|
}
|
||||||
writer.WriteLine("};");
|
writer.WriteLine("};");
|
||||||
@@ -366,7 +363,9 @@ public class Generator
|
|||||||
TypedNodeExpressionStringLiteral expression => $"({CType(expression.Type)}){{ \"{expression.Value.Value}\", {expression.Value.Value.Length} }}",
|
TypedNodeExpressionStringLiteral expression => $"({CType(expression.Type)}){{ \"{expression.Value.Value}\", {expression.Value.Value.Length} }}",
|
||||||
TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression),
|
TypedNodeExpressionStructLiteral expression => EmitExpressionStructLiteral(expression),
|
||||||
TypedNodeExpressionEnumLiteral expression => EmitExpressionEnumLiteral(expression),
|
TypedNodeExpressionEnumLiteral expression => EmitExpressionEnumLiteral(expression),
|
||||||
TypedNodeExpressionMemberAccess expression => EmitExpressionMemberAccess(expression),
|
TypedNodeExpressionStructMemberAccess expression => EmitExpressionMemberAccess(expression),
|
||||||
|
TypedNodeExpressionStringLength expression => EmitExpressionStringLength(expression),
|
||||||
|
TypedNodeExpressionStringPointer expression => EmitExpressionStringPointer(expression),
|
||||||
TypedNodeExpressionLocalIdent expression => expression.Name,
|
TypedNodeExpressionLocalIdent expression => expression.Name,
|
||||||
TypedNodeExpressionGlobalIdent expression => EmitNodeExpressionGlobalIdent(expression),
|
TypedNodeExpressionGlobalIdent expression => EmitNodeExpressionGlobalIdent(expression),
|
||||||
TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression),
|
TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression),
|
||||||
@@ -442,12 +441,24 @@ public class Generator
|
|||||||
return $"({CType(expression.Type)}){{ .tag = {tag}, .{enumVariantType.Variant} = {value} }}";
|
return $"({CType(expression.Type)}){{ .tag = {tag}, .{enumVariantType.Variant} = {value} }}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitExpressionMemberAccess(TypedNodeExpressionMemberAccess expression)
|
private string EmitExpressionMemberAccess(TypedNodeExpressionStructMemberAccess expression)
|
||||||
{
|
{
|
||||||
var target = EmitExpression(expression.Target);
|
var target = EmitExpression(expression.Target);
|
||||||
return $"{target}.{expression.Name.Ident}";
|
return $"{target}.{expression.Name.Ident}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string EmitExpressionStringLength(TypedNodeExpressionStringLength expression)
|
||||||
|
{
|
||||||
|
var target = EmitExpression(expression.Target);
|
||||||
|
return $"{target}.length";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EmitExpressionStringPointer(TypedNodeExpressionStringPointer expression)
|
||||||
|
{
|
||||||
|
var target = EmitExpression(expression.Target);
|
||||||
|
return $"{target}.data";
|
||||||
|
}
|
||||||
|
|
||||||
private string EmitNodeExpressionGlobalIdent(TypedNodeExpressionGlobalIdent expression)
|
private string EmitNodeExpressionGlobalIdent(TypedNodeExpressionGlobalIdent expression)
|
||||||
{
|
{
|
||||||
if (!moduleGraph.TryResolveIdentifier(expression.Module, expression.Name, true, out var info))
|
if (!moduleGraph.TryResolveIdentifier(expression.Module, expression.Name, true, out var info))
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public class ModuleGraph
|
|||||||
{
|
{
|
||||||
case Manifest.Module.TypeInfoStruct s:
|
case Manifest.Module.TypeInfoStruct s:
|
||||||
{
|
{
|
||||||
var info = new Module.TypeInfoStruct(Module.DefinitionKind.External, s.Packed);
|
var info = new Module.TypeInfoStruct(Module.DefinitionSource.Imported, true, s.Packed);
|
||||||
var fields = s.Fields.Select(x => new Module.TypeInfoStruct.Field(x.Name, x.Type)).ToList();
|
var fields = s.Fields.Select(x => new Module.TypeInfoStruct.Field(x.Name, x.Type)).ToList();
|
||||||
info.SetFields(fields);
|
info.SetFields(fields);
|
||||||
module.AddType(name, info);
|
module.AddType(name, info);
|
||||||
@@ -94,7 +94,7 @@ public class ModuleGraph
|
|||||||
}
|
}
|
||||||
case Manifest.Module.TypeInfoEnum s:
|
case Manifest.Module.TypeInfoEnum s:
|
||||||
{
|
{
|
||||||
var info = new Module.TypeInfoEnum(Module.DefinitionKind.External);
|
var info = new Module.TypeInfoEnum(Module.DefinitionSource.Imported, true);
|
||||||
var variants = s.Variants.Select(v => new Module.TypeInfoEnum.Variant(v.Name, v.Type)).ToList();
|
var variants = s.Variants.Select(v => new Module.TypeInfoEnum.Variant(v.Name, v.Type)).ToList();
|
||||||
info.SetVariants(variants);
|
info.SetVariants(variants);
|
||||||
module.AddType(name, info);
|
module.AddType(name, info);
|
||||||
@@ -107,7 +107,7 @@ public class ModuleGraph
|
|||||||
|
|
||||||
foreach (var (name, identifier) in manifestModule.Identifiers)
|
foreach (var (name, identifier) in manifestModule.Identifiers)
|
||||||
{
|
{
|
||||||
module.AddIdentifier(name, new Module.IdentifierInfo(Module.DefinitionKind.External, identifier.Type, identifier.MangledName));
|
module.AddIdentifier(name, new Module.IdentifierInfo(Module.DefinitionSource.Imported, true, true, identifier.Type, identifier.MangledName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,14 +118,12 @@ public class ModuleGraph
|
|||||||
|
|
||||||
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
|
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
|
||||||
{
|
{
|
||||||
var kind = structDef.Exported ? Module.DefinitionKind.Exported : Module.DefinitionKind.Internal;
|
module.AddType(structDef.Name.Ident, new Module.TypeInfoStruct(Module.DefinitionSource.Internal, structDef.Exported, structDef.Packed));
|
||||||
module.AddType(structDef.Name.Ident, new Module.TypeInfoStruct(kind, structDef.Packed));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var enumDef in ast.Definitions.OfType<NodeDefinitionEnum>())
|
foreach (var enumDef in ast.Definitions.OfType<NodeDefinitionEnum>())
|
||||||
{
|
{
|
||||||
var kind = enumDef.Exported ? Module.DefinitionKind.Exported : Module.DefinitionKind.Internal;
|
module.AddType(enumDef.Name.Ident, new Module.TypeInfoEnum(Module.DefinitionSource.Internal, enumDef.Exported));
|
||||||
module.AddType(enumDef.Name.Ident, new Module.TypeInfoEnum(kind));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,18 +163,32 @@ public class ModuleGraph
|
|||||||
foreach (var funcDef in ast.Definitions.OfType<NodeDefinitionFunc>())
|
foreach (var funcDef in ast.Definitions.OfType<NodeDefinitionFunc>())
|
||||||
{
|
{
|
||||||
var parameters = funcDef.Parameters.Select(x => ResolveType(x.Type, module.Name)).ToList();
|
var parameters = funcDef.Parameters.Select(x => ResolveType(x.Type, module.Name)).ToList();
|
||||||
var returnType = ResolveType(funcDef.ReturnType, module.Name);
|
var returnType = funcDef.ReturnType == null ? NubTypeVoid.Instance : ResolveType(funcDef.ReturnType, module.Name);
|
||||||
var funcType = NubTypeFunc.Get(parameters, returnType);
|
var funcType = NubTypeFunc.Get(parameters, returnType);
|
||||||
var kind = funcDef.Exported ? Module.DefinitionKind.Exported : Module.DefinitionKind.Internal;
|
var info = new Module.IdentifierInfo(Module.DefinitionSource.Internal, funcDef.Exported, false, funcType, NameMangler.Mangle(module.Name, funcDef.Name.Ident, funcType));
|
||||||
var info = new Module.IdentifierInfo(kind, funcType, NameMangler.Mangle(module.Name, funcDef.Name.Ident, funcType));
|
module.AddIdentifier(funcDef.Name.Ident, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var funcDef in ast.Definitions.OfType<NodeDefinitionExternFunc>())
|
||||||
|
{
|
||||||
|
var parameters = funcDef.Parameters.Select(x => ResolveType(x.Type, module.Name)).ToList();
|
||||||
|
var returnType = funcDef.ReturnType == null ? NubTypeVoid.Instance : ResolveType(funcDef.ReturnType, module.Name);
|
||||||
|
var funcType = NubTypeFunc.Get(parameters, returnType);
|
||||||
|
var info = new Module.IdentifierInfo(Module.DefinitionSource.Internal, funcDef.Exported, true, funcType, funcDef.Name.Ident);
|
||||||
module.AddIdentifier(funcDef.Name.Ident, info);
|
module.AddIdentifier(funcDef.Name.Ident, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var globalVariable in ast.Definitions.OfType<NodeDefinitionGlobalVariable>())
|
foreach (var globalVariable in ast.Definitions.OfType<NodeDefinitionGlobalVariable>())
|
||||||
{
|
{
|
||||||
var type = ResolveType(globalVariable.Type, module.Name);
|
var type = ResolveType(globalVariable.Type, module.Name);
|
||||||
var kind = globalVariable.Exported ? Module.DefinitionKind.Exported : Module.DefinitionKind.Internal;
|
var info = new Module.IdentifierInfo(Module.DefinitionSource.Internal, globalVariable.Exported, false, type, NameMangler.Mangle(module.Name, globalVariable.Name.Ident, type));
|
||||||
var info = new Module.IdentifierInfo(kind, type, NameMangler.Mangle(module.Name, globalVariable.Name.Ident, type));
|
module.AddIdentifier(globalVariable.Name.Ident, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var globalVariable in ast.Definitions.OfType<NodeDefinitionExternGlobalVariable>())
|
||||||
|
{
|
||||||
|
var type = ResolveType(globalVariable.Type, module.Name);
|
||||||
|
var info = new Module.IdentifierInfo(Module.DefinitionSource.Internal, globalVariable.Exported, true, type, NameMangler.Mangle(module.Name, globalVariable.Name.Ident, type));
|
||||||
module.AddIdentifier(globalVariable.Name.Ident, info);
|
module.AddIdentifier(globalVariable.Name.Ident, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,7 +345,7 @@ public class Module(string name)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchPrivate || info.Kind is DefinitionKind.External or DefinitionKind.Exported)
|
if (searchPrivate || info.Source == DefinitionSource.Internal)
|
||||||
{
|
{
|
||||||
customType = info;
|
customType = info;
|
||||||
return true;
|
return true;
|
||||||
@@ -352,7 +364,7 @@ public class Module(string name)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchPrivate || info.Kind is DefinitionKind.External or DefinitionKind.Exported)
|
if (searchPrivate || info.Source == DefinitionSource.Internal)
|
||||||
{
|
{
|
||||||
identifierType = info;
|
identifierType = info;
|
||||||
return true;
|
return true;
|
||||||
@@ -372,26 +384,28 @@ public class Module(string name)
|
|||||||
identifiers.Add(name, info);
|
identifiers.Add(name, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DefinitionKind
|
public enum DefinitionSource
|
||||||
{
|
{
|
||||||
Internal,
|
Internal,
|
||||||
Exported,
|
Imported,
|
||||||
External,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class IdentifierInfo(DefinitionKind kind, NubType type, string mangledName)
|
public class IdentifierInfo(DefinitionSource source, bool exported, bool @extern, NubType type, string mangledName)
|
||||||
{
|
{
|
||||||
public DefinitionKind Kind { get; } = kind;
|
public DefinitionSource Source { get; } = source;
|
||||||
|
public bool Exported { get; } = exported;
|
||||||
|
public bool Extern { get; } = @extern;
|
||||||
public NubType Type { get; } = type;
|
public NubType Type { get; } = type;
|
||||||
public string MangledName { get; } = mangledName;
|
public string MangledName { get; } = mangledName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class TypeInfo(DefinitionKind kind)
|
public abstract class TypeInfo(DefinitionSource source, bool exported)
|
||||||
{
|
{
|
||||||
public DefinitionKind Kind { get; } = kind;
|
public DefinitionSource Source { get; } = source;
|
||||||
|
public bool Exported { get; } = exported;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TypeInfoStruct(DefinitionKind kind, bool packed) : TypeInfo(kind)
|
public class TypeInfoStruct(DefinitionSource source, bool exported, bool packed) : TypeInfo(source, exported)
|
||||||
{
|
{
|
||||||
private IReadOnlyList<Field>? fields;
|
private IReadOnlyList<Field>? fields;
|
||||||
|
|
||||||
@@ -410,7 +424,7 @@ public class Module(string name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TypeInfoEnum(DefinitionKind kind) : TypeInfo(kind)
|
public class TypeInfoEnum(DefinitionSource source, bool exported) : TypeInfo(source, exported)
|
||||||
{
|
{
|
||||||
private IReadOnlyList<Variant>? variants;
|
private IReadOnlyList<Variant>? variants;
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public record Manifest(Dictionary<string, Manifest.Module> Modules)
|
|||||||
|
|
||||||
foreach (var (name, typeInfo) in module.GetTypes())
|
foreach (var (name, typeInfo) in module.GetTypes())
|
||||||
{
|
{
|
||||||
if (typeInfo.Kind == Compiler.Module.DefinitionKind.Exported)
|
if (typeInfo.Exported)
|
||||||
{
|
{
|
||||||
types.Add(name, ConvertType(typeInfo));
|
types.Add(name, ConvertType(typeInfo));
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ public record Manifest(Dictionary<string, Manifest.Module> Modules)
|
|||||||
|
|
||||||
foreach (var (name, identifierInfo) in module.GetIdentifiers())
|
foreach (var (name, identifierInfo) in module.GetIdentifiers())
|
||||||
{
|
{
|
||||||
if (identifierInfo.Kind == Compiler.Module.DefinitionKind.Exported)
|
if (identifierInfo.Exported)
|
||||||
{
|
{
|
||||||
identifiers.Add(name, new Module.IdentifierInfo(identifierInfo.Type, identifierInfo.MangledName));
|
identifiers.Add(name, new Module.IdentifierInfo(identifierInfo.Type, identifierInfo.MangledName));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ public class Parser
|
|||||||
Next();
|
Next();
|
||||||
modifiers[Keyword.Packed] = keyword;
|
modifiers[Keyword.Packed] = keyword;
|
||||||
break;
|
break;
|
||||||
|
case Keyword.Extern:
|
||||||
|
Next();
|
||||||
|
modifiers[Keyword.Extern] = keyword;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto modifier_done;
|
goto modifier_done;
|
||||||
}
|
}
|
||||||
@@ -75,6 +79,7 @@ public class Parser
|
|||||||
if (TryExpectKeyword(Keyword.Func))
|
if (TryExpectKeyword(Keyword.Func))
|
||||||
{
|
{
|
||||||
var exported = modifiers.Remove(Keyword.Export);
|
var exported = modifiers.Remove(Keyword.Export);
|
||||||
|
var @extern = modifiers.Remove(Keyword.Extern);
|
||||||
|
|
||||||
foreach (var modifier in modifiers)
|
foreach (var modifier in modifiers)
|
||||||
// todo(nub31): Add to diagnostics instead of throwing
|
// todo(nub31): Add to diagnostics instead of throwing
|
||||||
@@ -93,13 +98,20 @@ public class Parser
|
|||||||
parameters.Add(new NodeDefinitionFunc.Param(TokensFrom(paramStartIndex), parameterName, parameterType));
|
parameters.Add(new NodeDefinitionFunc.Param(TokensFrom(paramStartIndex), parameterName, parameterType));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectSymbol(Symbol.Colon);
|
NodeType? returnType = null;
|
||||||
var returnType = ParseType();
|
if (TryExpectSymbol(Symbol.Colon))
|
||||||
|
returnType = ParseType();
|
||||||
|
|
||||||
|
if (@extern)
|
||||||
|
{
|
||||||
|
return new NodeDefinitionExternFunc(TokensFrom(startIndex), exported, name, parameters, returnType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
var body = ParseStatement();
|
var body = ParseStatement();
|
||||||
|
|
||||||
return new NodeDefinitionFunc(TokensFrom(startIndex), exported, name, parameters, body, returnType);
|
return new NodeDefinitionFunc(TokensFrom(startIndex), exported, name, parameters, body, returnType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (TryExpectKeyword(Keyword.Struct))
|
if (TryExpectKeyword(Keyword.Struct))
|
||||||
{
|
{
|
||||||
@@ -704,13 +716,21 @@ public abstract class Node(List<Token> tokens)
|
|||||||
|
|
||||||
public abstract class NodeDefinition(List<Token> tokens) : Node(tokens);
|
public abstract class NodeDefinition(List<Token> tokens) : Node(tokens);
|
||||||
|
|
||||||
public class NodeDefinitionFunc(List<Token> tokens, bool exported, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens)
|
public class NodeDefinitionExternFunc(List<Token> tokens, bool exported, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeType? returnType) : NodeDefinition(tokens)
|
||||||
|
{
|
||||||
|
public bool Exported { get; } = exported;
|
||||||
|
public TokenIdent Name { get; } = name;
|
||||||
|
public List<NodeDefinitionFunc.Param> Parameters { get; } = parameters;
|
||||||
|
public NodeType? ReturnType { get; } = returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NodeDefinitionFunc(List<Token> tokens, bool exported, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType? returnType) : NodeDefinition(tokens)
|
||||||
{
|
{
|
||||||
public bool Exported { get; } = exported;
|
public bool Exported { get; } = exported;
|
||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
public List<Param> Parameters { get; } = parameters;
|
public List<Param> Parameters { get; } = parameters;
|
||||||
public NodeStatement Body { get; } = body;
|
public NodeStatement Body { get; } = body;
|
||||||
public NodeType ReturnType { get; } = returnType;
|
public NodeType? ReturnType { get; } = returnType;
|
||||||
|
|
||||||
public class Param(List<Token> tokens, TokenIdent name, NodeType type) : Node(tokens)
|
public class Param(List<Token> tokens, TokenIdent name, NodeType type) : Node(tokens)
|
||||||
{
|
{
|
||||||
@@ -746,6 +766,13 @@ public class NodeDefinitionEnum(List<Token> tokens, bool exported, TokenIdent na
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class NodeDefinitionExternGlobalVariable(List<Token> tokens, bool exported, TokenIdent name, NodeType type) : NodeDefinition(tokens)
|
||||||
|
{
|
||||||
|
public bool Exported { get; } = exported;
|
||||||
|
public TokenIdent Name { get; } = name;
|
||||||
|
public NodeType Type { get; } = type;
|
||||||
|
}
|
||||||
|
|
||||||
public class NodeDefinitionGlobalVariable(List<Token> tokens, bool exported, TokenIdent name, NodeType type) : NodeDefinition(tokens)
|
public class NodeDefinitionGlobalVariable(List<Token> tokens, bool exported, TokenIdent name, NodeType type) : NodeDefinition(tokens)
|
||||||
{
|
{
|
||||||
public bool Exported { get; } = exported;
|
public bool Exported { get; } = exported;
|
||||||
|
|||||||
@@ -133,13 +133,13 @@ File.WriteAllText(".build/out.c", output);
|
|||||||
|
|
||||||
if (compileLib)
|
if (compileLib)
|
||||||
{
|
{
|
||||||
Process.Start("gcc", ["-Og", "-fvisibility=hidden", "-fno-builtin", "-c", "-o", ".build/out.o", ".build/out.c", .. archivePaths]).WaitForExit();
|
Process.Start("gcc", ["-Og", "-fno-builtin", "-c", "-o", ".build/out.o", ".build/out.c", .. archivePaths]).WaitForExit();
|
||||||
Process.Start("ar", ["rcs", ".build/out.a", ".build/out.o"]).WaitForExit();
|
Process.Start("ar", ["rcs", ".build/out.a", ".build/out.o"]).WaitForExit();
|
||||||
NubLib.Pack(".build/out.nublib", ".build/out.a", Manifest.Create(moduleGraph));
|
NubLib.Pack(".build/out.nublib", ".build/out.a", Manifest.Create(moduleGraph));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Process.Start("gcc", ["-Og", "-fvisibility=hidden", "-fno-builtin", "-o", ".build/out", ".build/out.c", .. archivePaths]).WaitForExit();
|
Process.Start("gcc", ["-Og", "-fno-builtin", "-o", ".build/out", ".build/out.c", .. archivePaths]).WaitForExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -397,6 +397,7 @@ public class Tokenizer
|
|||||||
"return" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Return),
|
"return" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Return),
|
||||||
"module" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Module),
|
"module" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Module),
|
||||||
"export" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Export),
|
"export" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Export),
|
||||||
|
"extern" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Extern),
|
||||||
"true" => new TokenBoolLiteral(line, startColumn, column - startColumn, true),
|
"true" => new TokenBoolLiteral(line, startColumn, column - startColumn, true),
|
||||||
"false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false),
|
"false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false),
|
||||||
_ => new TokenIdent(line, startColumn, column - startColumn, value)
|
_ => new TokenIdent(line, startColumn, column - startColumn, value)
|
||||||
@@ -545,6 +546,7 @@ public enum Keyword
|
|||||||
Return,
|
Return,
|
||||||
Module,
|
Module,
|
||||||
Export,
|
Export,
|
||||||
|
Extern,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length)
|
public class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length)
|
||||||
@@ -611,6 +613,7 @@ public static class TokenExtensions
|
|||||||
Keyword.Return => "return",
|
Keyword.Return => "return",
|
||||||
Keyword.Module => "module",
|
Keyword.Module => "module",
|
||||||
Keyword.Export => "export",
|
Keyword.Export => "export",
|
||||||
|
Keyword.Extern => "extern",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(symbol), symbol, null)
|
_ => throw new ArgumentOutOfRangeException(nameof(symbol), symbol, null)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ public class TypeChecker
|
|||||||
var invalidParameter = false;
|
var invalidParameter = false;
|
||||||
TypedNodeStatement? body = null;
|
TypedNodeStatement? body = null;
|
||||||
|
|
||||||
|
if (function.ReturnType == null)
|
||||||
|
{
|
||||||
|
functionReturnType = NubTypeVoid.Instance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
functionReturnType = ResolveType(function.ReturnType);
|
functionReturnType = ResolveType(function.ReturnType);
|
||||||
@@ -43,6 +49,7 @@ public class TypeChecker
|
|||||||
diagnostics.Add(e.Diagnostic);
|
diagnostics.Add(e.Diagnostic);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using (scope.EnterScope())
|
using (scope.EnterScope())
|
||||||
{
|
{
|
||||||
@@ -395,15 +402,34 @@ public class TypeChecker
|
|||||||
|
|
||||||
private TypedNodeExpressionIntLiteral CheckExpressionIntLiteral(NodeExpressionIntLiteral expression, NubType? expectedType)
|
private TypedNodeExpressionIntLiteral CheckExpressionIntLiteral(NodeExpressionIntLiteral expression, NubType? expectedType)
|
||||||
{
|
{
|
||||||
return new TypedNodeExpressionIntLiteral(expression.Tokens, NubTypeSInt.Get(32), expression.Value);
|
NubType? type = null;
|
||||||
|
|
||||||
|
if (expectedType is NubTypeSInt or NubTypeUInt)
|
||||||
|
type = expectedType;
|
||||||
|
|
||||||
|
type ??= NubTypeSInt.Get(32);
|
||||||
|
|
||||||
|
return new TypedNodeExpressionIntLiteral(expression.Tokens, type, expression.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedNodeExpressionMemberAccess CheckExpressionMemberAccess(NodeExpressionMemberAccess expression, NubType? expectedType)
|
private TypedNodeExpression CheckExpressionMemberAccess(NodeExpressionMemberAccess expression, NubType? expectedType)
|
||||||
{
|
{
|
||||||
var target = CheckExpression(expression.Target, null);
|
var target = CheckExpression(expression.Target, null);
|
||||||
|
|
||||||
switch (target.Type)
|
switch (target.Type)
|
||||||
{
|
{
|
||||||
|
case NubTypeString stringType:
|
||||||
|
{
|
||||||
|
switch (expression.Name.Ident)
|
||||||
|
{
|
||||||
|
case "length":
|
||||||
|
return new TypedNodeExpressionStringLength(expression.Tokens, NubTypeUInt.Get(64), target);
|
||||||
|
case "ptr":
|
||||||
|
return new TypedNodeExpressionStringPointer(expression.Tokens, NubTypePointer.Get(NubTypeUInt.Get(8)), target);
|
||||||
|
default:
|
||||||
|
throw BasicError($"'{expression.Name.Ident}' is not a member of type string", expression.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
case NubTypeStruct structType:
|
case NubTypeStruct structType:
|
||||||
{
|
{
|
||||||
if (!moduleGraph.TryResolveModule(structType.Module, out var module))
|
if (!moduleGraph.TryResolveModule(structType.Module, out var module))
|
||||||
@@ -419,7 +445,7 @@ public class TypeChecker
|
|||||||
if (field == null)
|
if (field == null)
|
||||||
throw BasicError($"Struct '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'", target);
|
throw BasicError($"Struct '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'", target);
|
||||||
|
|
||||||
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
return new TypedNodeExpressionStructMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
||||||
}
|
}
|
||||||
case NubTypeAnonymousStruct anonymousStructType:
|
case NubTypeAnonymousStruct anonymousStructType:
|
||||||
{
|
{
|
||||||
@@ -427,24 +453,7 @@ public class TypeChecker
|
|||||||
if (field == null)
|
if (field == null)
|
||||||
throw BasicError($"Struct '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'", target);
|
throw BasicError($"Struct '{target.Type}' does not have a field matching the name '{expression.Name.Ident}'", target);
|
||||||
|
|
||||||
return new TypedNodeExpressionMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
return new TypedNodeExpressionStructMemberAccess(expression.Tokens, field.Type, target, expression.Name);
|
||||||
}
|
|
||||||
case NubTypeEnumVariant enumVariantType:
|
|
||||||
{
|
|
||||||
if (!moduleGraph.TryResolveModule(enumVariantType.EnumType.Module, out var module))
|
|
||||||
throw BasicError($"Module '{enumVariantType.EnumType.Module}' not found", expression.Target);
|
|
||||||
|
|
||||||
if (!module.TryResolveType(enumVariantType.EnumType.Name, currentModule == enumVariantType.EnumType.Module, out var typeDef))
|
|
||||||
throw BasicError($"Type '{enumVariantType.EnumType.Name}' not found in module '{enumVariantType.EnumType.Module}'", expression.Target);
|
|
||||||
|
|
||||||
if (typeDef is not Module.TypeInfoEnum enumDef)
|
|
||||||
throw BasicError($"Type '{enumVariantType.EnumType.Module}::{enumVariantType.EnumType.Name}' is not an enum", expression.Target);
|
|
||||||
|
|
||||||
var variant = enumDef.Variants.FirstOrDefault(x => x.Name == enumVariantType.Variant);
|
|
||||||
if (variant == null)
|
|
||||||
throw BasicError($"Type '{target.Type}' does not have a variant named '{enumVariantType.Variant}'", expression.Target);
|
|
||||||
|
|
||||||
return new TypedNodeExpressionMemberAccess(expression.Tokens, variant.Type, target, expression.Name);
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw BasicError($"{target.Type} has no member '{expression.Name.Ident}'", target);
|
throw BasicError($"{target.Type} has no member '{expression.Name.Ident}'", target);
|
||||||
@@ -867,12 +876,22 @@ public class TypedNodeExpressionEnumLiteral(List<Token> tokens, NubType type, Ty
|
|||||||
public TypedNodeExpression Value { get; } = value;
|
public TypedNodeExpression Value { get; } = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TypedNodeExpressionMemberAccess(List<Token> tokens, NubType type, TypedNodeExpression target, TokenIdent name) : TypedNodeExpression(tokens, type)
|
public class TypedNodeExpressionStructMemberAccess(List<Token> tokens, NubType type, TypedNodeExpression target, TokenIdent name) : TypedNodeExpression(tokens, type)
|
||||||
{
|
{
|
||||||
public TypedNodeExpression Target { get; } = target;
|
public TypedNodeExpression Target { get; } = target;
|
||||||
public TokenIdent Name { get; } = name;
|
public TokenIdent Name { get; } = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TypedNodeExpressionStringLength(List<Token> tokens, NubType type, TypedNodeExpression target) : TypedNodeExpression(tokens, type)
|
||||||
|
{
|
||||||
|
public TypedNodeExpression Target { get; } = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TypedNodeExpressionStringPointer(List<Token> tokens, NubType type, TypedNodeExpression target) : TypedNodeExpression(tokens, type)
|
||||||
|
{
|
||||||
|
public TypedNodeExpression Target { get; } = target;
|
||||||
|
}
|
||||||
|
|
||||||
public class TypedNodeExpressionFuncCall(List<Token> tokens, NubType type, TypedNodeExpression target, List<TypedNodeExpression> parameters) : TypedNodeExpression(tokens, type)
|
public class TypedNodeExpressionFuncCall(List<Token> tokens, NubType type, TypedNodeExpression target, List<TypedNodeExpression> parameters) : TypedNodeExpression(tokens, type)
|
||||||
{
|
{
|
||||||
public TypedNodeExpression Target { get; } = target;
|
public TypedNodeExpression Target { get; } = target;
|
||||||
|
|||||||
@@ -11,3 +11,5 @@ popd
|
|||||||
pushd program
|
pushd program
|
||||||
dotnet run --project ../../compiler main.nub ../math/.build/out.nublib ../core/.build/out.nublib
|
dotnet run --project ../../compiler main.nub ../math/.build/out.nublib ../core/.build/out.nublib
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
./program/.build/out
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
module print
|
module core
|
||||||
|
|
||||||
extern func puts(^u8 text)
|
export extern func malloc(size: u64): ^void
|
||||||
|
export extern func free(size: ^void)
|
||||||
|
|
||||||
export func print(text: string) {
|
extern func puts(text: ^u8)
|
||||||
|
|
||||||
|
export func print(text: string)
|
||||||
|
{
|
||||||
|
puts(text.ptr)
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,9 @@
|
|||||||
module main
|
module main
|
||||||
|
|
||||||
struct Pos {
|
|
||||||
x: i32
|
|
||||||
y: i32
|
|
||||||
}
|
|
||||||
|
|
||||||
func main(): i32
|
func main(): i32
|
||||||
{
|
{
|
||||||
test({ x = 23 y = 23 })
|
core::print("Hello, world")
|
||||||
|
let ptr = core::malloc(64)
|
||||||
return 1
|
core::free(ptr)
|
||||||
}
|
return 0
|
||||||
|
|
||||||
func test(x: Pos): void
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user