Merge pull request #35 from birth-software/c-libraries
implement extern functionality
This commit is contained in:
commit
76332f5ad7
@ -563,7 +563,6 @@ pub const Declaration = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Function = struct {
|
pub const Function = struct {
|
||||||
scope: Scope.Index,
|
|
||||||
body: Block.Index,
|
body: Block.Index,
|
||||||
prototype: Type.Index,
|
prototype: Type.Index,
|
||||||
|
|
||||||
@ -571,11 +570,12 @@ pub const Function = struct {
|
|||||||
arguments: ArrayList(Declaration.Index),
|
arguments: ArrayList(Declaration.Index),
|
||||||
return_type: Type.Index,
|
return_type: Type.Index,
|
||||||
attributes: Attributes = .{},
|
attributes: Attributes = .{},
|
||||||
|
scope: Scope.Index,
|
||||||
|
|
||||||
pub const List = BlockList(@This());
|
pub const List = BlockList(@This());
|
||||||
pub const Index = Prototype.List.Index;
|
pub const Index = Prototype.List.Index;
|
||||||
|
|
||||||
pub const Attributes = packed struct {
|
pub const Attributes = struct {
|
||||||
@"extern": bool = false,
|
@"extern": bool = false,
|
||||||
@"export": bool = false,
|
@"export": bool = false,
|
||||||
@"inline": Inline = .none,
|
@"inline": Inline = .none,
|
||||||
@ -885,7 +885,6 @@ pub const Value = union(enum) {
|
|||||||
indexed_access: IndexedAccess.Index,
|
indexed_access: IndexedAccess.Index,
|
||||||
optional_check: OptionalCheck.Index,
|
optional_check: OptionalCheck.Index,
|
||||||
optional_unwrap: OptionalUnwrap.Index,
|
optional_unwrap: OptionalUnwrap.Index,
|
||||||
// optional_cast: Cast.Index,
|
|
||||||
array_coerce_to_slice: Cast.Index,
|
array_coerce_to_slice: Cast.Index,
|
||||||
slice: Slice.Index,
|
slice: Slice.Index,
|
||||||
assembly_block: Assembly.Block.Index,
|
assembly_block: Assembly.Block.Index,
|
||||||
@ -908,9 +907,16 @@ pub const Value = union(enum) {
|
|||||||
_ = module;
|
_ = module;
|
||||||
|
|
||||||
return switch (value.*) {
|
return switch (value.*) {
|
||||||
|
.bool,
|
||||||
|
.void,
|
||||||
|
.function_definition,
|
||||||
|
.function_declaration,
|
||||||
|
.type,
|
||||||
|
.enum_field,
|
||||||
|
.string_literal,
|
||||||
|
=> true,
|
||||||
.integer => |integer| integer.type.eq(Type.comptime_int),
|
.integer => |integer| integer.type.eq(Type.comptime_int),
|
||||||
.declaration_reference => false,
|
.declaration_reference => false,
|
||||||
.bool, .void, .function_definition, .type, .enum_field => true,
|
|
||||||
// TODO:
|
// TODO:
|
||||||
.call,
|
.call,
|
||||||
// .syscall,
|
// .syscall,
|
||||||
@ -1048,7 +1054,8 @@ pub const Module = struct {
|
|||||||
function_prototypes: BlockList(Function.Prototype) = .{},
|
function_prototypes: BlockList(Function.Prototype) = .{},
|
||||||
} = .{},
|
} = .{},
|
||||||
map: struct {
|
map: struct {
|
||||||
functions: data_structures.AutoArrayHashMap(Function.Index, Declaration.Index) = .{},
|
function_definitions: data_structures.AutoArrayHashMap(Function.Index, Declaration.Index) = .{},
|
||||||
|
function_declarations: data_structures.AutoArrayHashMap(Function.Index, Declaration.Index) = .{},
|
||||||
strings: StringKeyMap([]const u8) = .{},
|
strings: StringKeyMap([]const u8) = .{},
|
||||||
imports: StringArrayHashMap(File.Index) = .{},
|
imports: StringArrayHashMap(File.Index) = .{},
|
||||||
types: data_structures.AutoArrayHashMap(Type.Index, Declaration.Index) = .{},
|
types: data_structures.AutoArrayHashMap(Type.Index, Declaration.Index) = .{},
|
||||||
@ -1057,6 +1064,7 @@ pub const Module = struct {
|
|||||||
pointers: data_structures.AutoArrayHashMap(Type.Pointer, Type.Index) = .{},
|
pointers: data_structures.AutoArrayHashMap(Type.Pointer, Type.Index) = .{},
|
||||||
optionals: data_structures.AutoArrayHashMap(Type.Index, Type.Index) = .{},
|
optionals: data_structures.AutoArrayHashMap(Type.Index, Type.Index) = .{},
|
||||||
arrays: data_structures.AutoArrayHashMap(Type.Array, Type.Index) = .{},
|
arrays: data_structures.AutoArrayHashMap(Type.Array, Type.Index) = .{},
|
||||||
|
libraries: data_structures.StringArrayHashMap(void) = .{},
|
||||||
} = .{},
|
} = .{},
|
||||||
main_package: *Package,
|
main_package: *Package,
|
||||||
entry_point: Function.Index = Function.Index.invalid,
|
entry_point: Function.Index = Function.Index.invalid,
|
||||||
|
@ -64,7 +64,8 @@ pub const TranslationUnit = struct {
|
|||||||
global_variable_declarations: ArrayList(u8) = .{},
|
global_variable_declarations: ArrayList(u8) = .{},
|
||||||
function_definitions: ArrayList(u8) = .{},
|
function_definitions: ArrayList(u8) = .{},
|
||||||
syscall_bitset: SyscallBitset = SyscallBitset.initEmpty(),
|
syscall_bitset: SyscallBitset = SyscallBitset.initEmpty(),
|
||||||
function_set: AutoArrayHashMap(Compilation.Function.Index, []const u8) = .{},
|
function_definition_set: AutoArrayHashMap(Compilation.Function.Index, []const u8) = .{},
|
||||||
|
function_declaration_set: AutoArrayHashMap(Compilation.Function.Index, []const u8) = .{},
|
||||||
macro_set: std.EnumSet(Macro) = std.EnumSet(Macro).initEmpty(),
|
macro_set: std.EnumSet(Macro) = std.EnumSet(Macro).initEmpty(),
|
||||||
struct_type_set: TypeSet = .{},
|
struct_type_set: TypeSet = .{},
|
||||||
optional_type_set: TypeSet = .{},
|
optional_type_set: TypeSet = .{},
|
||||||
@ -102,6 +103,13 @@ pub const TranslationUnit = struct {
|
|||||||
\\
|
\\
|
||||||
);
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
var function_declarations = module.types.function_declarations.iterator();
|
||||||
|
while (function_declarations.nextIndex()) |function_declaration_index| {
|
||||||
|
_ = try unit.writeFunctionDeclaration(module, allocator, function_declaration_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var function_definitions = module.types.function_definitions.iterator();
|
var function_definitions = module.types.function_definitions.iterator();
|
||||||
while (function_definitions.nextIndex()) |function_definition_index| {
|
while (function_definitions.nextIndex()) |function_definition_index| {
|
||||||
@ -112,18 +120,33 @@ pub const TranslationUnit = struct {
|
|||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn writeFunctionDeclaration(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_declaration_index: Compilation.Function.Index) ![]const u8 {
|
||||||
|
if (unit.function_declaration_set.getIndex(function_declaration_index)) |index| {
|
||||||
|
return unit.function_declaration_set.values()[index];
|
||||||
|
} else {
|
||||||
|
const function_name = try unit.renderFunctionDeclarationName(module, allocator, function_declaration_index);
|
||||||
|
try unit.writeFunctionHeader(module, &unit.function_declarations, allocator, module.types.function_declarations.get(function_declaration_index), function_name);
|
||||||
|
try unit.function_declaration_set.putNoClobber(allocator, function_declaration_index, function_name);
|
||||||
|
|
||||||
|
try unit.function_declarations.appendSlice(allocator, ";\n\n");
|
||||||
|
|
||||||
|
return function_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn writeFunctionDefinition(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_definition_index: Compilation.Function.Index) ![]const u8 {
|
fn writeFunctionDefinition(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_definition_index: Compilation.Function.Index) ![]const u8 {
|
||||||
if (unit.function_set.getIndex(function_definition_index)) |index| {
|
if (unit.function_definition_set.getIndex(function_definition_index)) |index| {
|
||||||
return unit.function_set.values()[index];
|
return unit.function_definition_set.values()[index];
|
||||||
} else {
|
} else {
|
||||||
const function_definition = module.types.function_definitions.get(function_definition_index);
|
const function_definition = module.types.function_definitions.get(function_definition_index);
|
||||||
const function_prototype_type = function_definition.prototype;
|
const function_prototype_type = function_definition.prototype;
|
||||||
const function_prototype = module.types.function_prototypes.get(module.types.array.get(function_prototype_type).function);
|
const function_prototype = module.types.function_prototypes.get(module.types.array.get(function_prototype_type).function);
|
||||||
|
|
||||||
const function_name = try unit.writeFunctionHeader(module, &unit.function_declarations, allocator, function_definition_index);
|
const function_name = try unit.renderFunctionDefinitionName(module, allocator, function_definition_index);
|
||||||
try unit.function_set.putNoClobber(allocator, function_definition_index, function_name);
|
try unit.writeFunctionHeader(module, &unit.function_declarations, allocator, function_definition, function_name);
|
||||||
|
try unit.function_definition_set.putNoClobber(allocator, function_definition_index, function_name);
|
||||||
|
|
||||||
_ = try unit.writeFunctionHeader(module, &unit.function_definitions, allocator, function_definition_index);
|
try unit.writeFunctionHeader(module, &unit.function_definitions, allocator, function_definition, function_name);
|
||||||
try unit.function_declarations.appendSlice(allocator, ";\n\n");
|
try unit.function_declarations.appendSlice(allocator, ";\n\n");
|
||||||
|
|
||||||
try unit.function_definitions.append(allocator, ' ');
|
try unit.function_definitions.append(allocator, ' ');
|
||||||
@ -387,17 +410,28 @@ pub const TranslationUnit = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderFunctionName(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_index: Compilation.Function.Index) ![]const u8 {
|
fn renderFunctionDefinitionName(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_definition_index: Compilation.Function.Index) ![]const u8 {
|
||||||
const function_definition = module.types.function_definitions.get(function_index);
|
const function_definition = module.types.function_definitions.get(function_definition_index);
|
||||||
const function_prototype_type = module.types.array.get(function_definition.prototype);
|
const function_prototype_type = module.types.array.get(function_definition.prototype);
|
||||||
const function_prototype_index = function_prototype_type.function;
|
const function_prototype_index = function_prototype_type.function;
|
||||||
const function_prototype = module.types.function_prototypes.get(function_prototype_index);
|
const function_prototype = module.types.function_prototypes.get(function_prototype_index);
|
||||||
const mangle = !(function_prototype.attributes.@"export" or function_prototype.attributes.@"extern");
|
const mangle = !(function_prototype.attributes.@"export" or function_prototype.attributes.@"extern");
|
||||||
const function_declaration_index = module.map.functions.get(function_index).?;
|
const function_declaration_index = module.map.function_definitions.get(function_definition_index).?;
|
||||||
const name = try unit.renderDeclarationName(module, allocator, function_declaration_index, mangle);
|
const name = try unit.renderDeclarationName(module, allocator, function_declaration_index, mangle);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn renderFunctionDeclarationName(unit: *TranslationUnit, module: *Module, allocator: Allocator, function_declaration_index: Compilation.Function.Index) ![]const u8 {
|
||||||
|
const function_declaration = module.types.function_declarations.get(function_declaration_index);
|
||||||
|
const function_prototype_type = module.types.array.get(function_declaration.prototype);
|
||||||
|
const function_prototype_index = function_prototype_type.function;
|
||||||
|
const function_prototype = module.types.function_prototypes.get(function_prototype_index);
|
||||||
|
const mangle = !(function_prototype.attributes.@"export" or function_prototype.attributes.@"extern");
|
||||||
|
const declaration_index = module.map.function_declarations.get(function_declaration_index).?;
|
||||||
|
const name = try unit.renderDeclarationName(module, allocator, declaration_index, mangle);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
fn renderDeclarationName(unit: *TranslationUnit, module: *Module, allocator: Allocator, declaration_index: Compilation.Declaration.Index, mangle: bool) anyerror![]const u8 {
|
fn renderDeclarationName(unit: *TranslationUnit, module: *Module, allocator: Allocator, declaration_index: Compilation.Declaration.Index, mangle: bool) anyerror![]const u8 {
|
||||||
if (unit.declaration_set.getIndex(declaration_index)) |index| {
|
if (unit.declaration_set.getIndex(declaration_index)) |index| {
|
||||||
return unit.declaration_set.values()[index];
|
return unit.declaration_set.values()[index];
|
||||||
@ -481,6 +515,11 @@ pub const TranslationUnit = struct {
|
|||||||
try list.appendSlice(allocator, "int main(int argc, char** argv, char** envp)");
|
try list.appendSlice(allocator, "int main(int argc, char** argv, char** envp)");
|
||||||
} else {
|
} else {
|
||||||
const function_prototype = module.types.function_prototypes.get(function_prototype_index);
|
const function_prototype = module.types.function_prototypes.get(function_prototype_index);
|
||||||
|
|
||||||
|
if (function_prototype.attributes.@"extern") {
|
||||||
|
try list.appendSlice(allocator, "extern ");
|
||||||
|
}
|
||||||
|
|
||||||
switch (function_prototype.attributes.calling_convention) {
|
switch (function_prototype.attributes.calling_convention) {
|
||||||
.system_v => {},
|
.system_v => {},
|
||||||
.naked => try list.appendSlice(allocator, "[[gnu::naked]] "),
|
.naked => try list.appendSlice(allocator, "[[gnu::naked]] "),
|
||||||
@ -494,14 +533,12 @@ pub const TranslationUnit = struct {
|
|||||||
|
|
||||||
try list.append(allocator, '(');
|
try list.append(allocator, '(');
|
||||||
|
|
||||||
|
|
||||||
if (function_prototype.arguments.items.len > 0) {
|
if (function_prototype.arguments.items.len > 0) {
|
||||||
for (function_prototype.arguments.items, 0..) |argument_index, index| {
|
for (function_prototype.arguments.items, 0..) |argument_index, index| {
|
||||||
_ = index;
|
_ = index;
|
||||||
|
|
||||||
const arg_declaration = module.values.declarations.get(argument_index);
|
const arg_declaration = module.values.declarations.get(argument_index);
|
||||||
if (is_main) {
|
if (is_main) {} else {
|
||||||
} else {
|
|
||||||
try unit.writeType(module, list, allocator, arg_declaration.getType(), ' ');
|
try unit.writeType(module, list, allocator, arg_declaration.getType(), ' ');
|
||||||
}
|
}
|
||||||
try list.append(allocator, ' ');
|
try list.append(allocator, ' ');
|
||||||
@ -517,15 +554,11 @@ pub const TranslationUnit = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeFunctionHeader(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, function_index: Compilation.Function.Index) ![]const u8 {
|
fn writeFunctionHeader(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, function: *const Compilation.Function, name: []const u8) !void {
|
||||||
const name = try unit.renderFunctionName(module, allocator, function_index);
|
const function_prototype_type = module.types.array.get(function.prototype);
|
||||||
const function_definition = module.types.function_definitions.get(function_index);
|
|
||||||
const function_prototype_type = module.types.array.get(function_definition.prototype);
|
|
||||||
const function_prototype_index = function_prototype_type.function;
|
const function_prototype_index = function_prototype_type.function;
|
||||||
|
|
||||||
try unit.writeFunctionPrototype(module, list, allocator, function_prototype_index, name);
|
try unit.writeFunctionPrototype(module, list, allocator, function_prototype_index, name);
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeType(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, type_index: Type.Index, separation_character: u8) anyerror!void {
|
fn writeType(unit: *TranslationUnit, module: *Module, list: *ArrayList(u8), allocator: Allocator, type_index: Type.Index, separation_character: u8) anyerror!void {
|
||||||
@ -1241,12 +1274,10 @@ pub const TranslationUnit = struct {
|
|||||||
const call = module.values.calls.get(call_index);
|
const call = module.values.calls.get(call_index);
|
||||||
const call_value = module.values.array.get(call.value);
|
const call_value = module.values.array.get(call.value);
|
||||||
var argument_declarations = ArrayList(Compilation.Declaration.Index){};
|
var argument_declarations = ArrayList(Compilation.Declaration.Index){};
|
||||||
switch (call_value.*) {
|
|
||||||
.function_definition => |function_definition_index| {
|
const callable_name = switch (call_value.*) {
|
||||||
const name = try unit.renderFunctionName(module, allocator, function_definition_index);
|
.function_definition => |function_definition_index| blk: {
|
||||||
// if (equal(u8, name, "os_execute")) {
|
const name = try unit.renderFunctionDefinitionName(module, allocator, function_definition_index);
|
||||||
// @breakpoint();
|
|
||||||
// }
|
|
||||||
const function_definition = module.types.function_definitions.get(function_definition_index);
|
const function_definition = module.types.function_definitions.get(function_definition_index);
|
||||||
const function_prototype_type = module.types.array.get(function_definition.prototype);
|
const function_prototype_type = module.types.array.get(function_definition.prototype);
|
||||||
const function_prototype = module.types.function_prototypes.get(function_prototype_type.function);
|
const function_prototype = module.types.function_prototypes.get(function_prototype_type.function);
|
||||||
@ -1254,8 +1285,22 @@ pub const TranslationUnit = struct {
|
|||||||
|
|
||||||
try list.appendSlice(allocator, name);
|
try list.appendSlice(allocator, name);
|
||||||
try list.append(allocator, '(');
|
try list.append(allocator, '(');
|
||||||
|
|
||||||
|
break :blk name;
|
||||||
},
|
},
|
||||||
.field_access => |field_access_index| {
|
.function_declaration => |function_declaration_index| blk: {
|
||||||
|
const name = try unit.renderFunctionDeclarationName(module, allocator, function_declaration_index);
|
||||||
|
const function_declaration = module.types.function_declarations.get(function_declaration_index);
|
||||||
|
const function_prototype_type = module.types.array.get(function_declaration.prototype);
|
||||||
|
const function_prototype = module.types.function_prototypes.get(function_prototype_type.function);
|
||||||
|
argument_declarations = function_prototype.arguments;
|
||||||
|
|
||||||
|
try list.appendSlice(allocator, name);
|
||||||
|
try list.append(allocator, '(');
|
||||||
|
|
||||||
|
break :blk name;
|
||||||
|
},
|
||||||
|
.field_access => |field_access_index| blk: {
|
||||||
const field_access = module.values.field_accesses.get(field_access_index);
|
const field_access = module.values.field_accesses.get(field_access_index);
|
||||||
try unit.writeValue(module, list, allocator, function_return_type, indentation, .{
|
try unit.writeValue(module, list, allocator, function_return_type, indentation, .{
|
||||||
.value_index = field_access.declaration_reference,
|
.value_index = field_access.declaration_reference,
|
||||||
@ -1291,9 +1336,11 @@ pub const TranslationUnit = struct {
|
|||||||
const field_name = module.getName(field.name).?;
|
const field_name = module.getName(field.name).?;
|
||||||
try list.appendSlice(allocator, field_name);
|
try list.appendSlice(allocator, field_name);
|
||||||
try list.append(allocator, '(');
|
try list.append(allocator, '(');
|
||||||
|
break :blk "field_access";
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
};
|
||||||
|
_ = callable_name;
|
||||||
|
|
||||||
if (!call.arguments.invalid) {
|
if (!call.arguments.invalid) {
|
||||||
const argument_list = module.values.argument_lists.get(call.arguments);
|
const argument_list = module.values.argument_lists.get(call.arguments);
|
||||||
@ -1961,6 +2008,11 @@ pub fn initialize(compilation: *Compilation, module: *Module) !void {
|
|||||||
try zig_command_line.append(allocator, "-lc");
|
try zig_command_line.append(allocator, "-lc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (module.map.libraries.keys()) |library_name| {
|
||||||
|
const library_argument = try std.mem.concat(allocator, u8, &.{ "-l", library_name });
|
||||||
|
try zig_command_line.append(allocator, library_argument);
|
||||||
|
}
|
||||||
|
|
||||||
const local_cache_dir = std.fs.cwd().realpathAlloc(allocator, "zig-cache") catch b: {
|
const local_cache_dir = std.fs.cwd().realpathAlloc(allocator, "zig-cache") catch b: {
|
||||||
std.fs.cwd().makeDir("nat/zig-cache") catch {};
|
std.fs.cwd().makeDir("nat/zig-cache") catch {};
|
||||||
break :b try std.fs.cwd().realpathAlloc(allocator, "nat/zig-cache");
|
break :b try std.fs.cwd().realpathAlloc(allocator, "nat/zig-cache");
|
||||||
@ -1972,7 +2024,6 @@ pub fn initialize(compilation: *Compilation, module: *Module) !void {
|
|||||||
try zig_command_line.append(allocator, "--global-cache-dir");
|
try zig_command_line.append(allocator, "--global-cache-dir");
|
||||||
try zig_command_line.append(allocator, global_cache_dir);
|
try zig_command_line.append(allocator, global_cache_dir);
|
||||||
|
|
||||||
|
|
||||||
try zig_command_line.append(allocator, try std.mem.concat(allocator, u8, &.{ "-femit-bin=", module.descriptor.executable_path }));
|
try zig_command_line.append(allocator, try std.mem.concat(allocator, u8, &.{ "-femit-bin=", module.descriptor.executable_path }));
|
||||||
try zig_command_line.append(allocator, "-cflags");
|
try zig_command_line.append(allocator, "-cflags");
|
||||||
|
|
||||||
|
@ -667,6 +667,7 @@ const Analyzer = struct {
|
|||||||
const left_type = switch (left_value_index.invalid) {
|
const left_type = switch (left_value_index.invalid) {
|
||||||
false => switch (analyzer.module.values.array.get(left_value_index).*) {
|
false => switch (analyzer.module.values.array.get(left_value_index).*) {
|
||||||
.function_definition => |function_index| analyzer.module.types.function_prototypes.get(analyzer.module.types.array.get(analyzer.module.types.function_definitions.get(function_index).prototype).function).return_type,
|
.function_definition => |function_index| analyzer.module.types.function_prototypes.get(analyzer.module.types.array.get(analyzer.module.types.function_definitions.get(function_index).prototype).function).return_type,
|
||||||
|
.function_declaration => |function_index| analyzer.module.types.function_prototypes.get(analyzer.module.types.array.get(analyzer.module.types.function_declarations.get(function_index).prototype).function).return_type,
|
||||||
.field_access => |field_access_index| blk: {
|
.field_access => |field_access_index| blk: {
|
||||||
const field_access_type_index = analyzer.module.types.container_fields.get(analyzer.module.values.field_accesses.get(field_access_index).field).type;
|
const field_access_type_index = analyzer.module.types.container_fields.get(analyzer.module.values.field_accesses.get(field_access_index).field).type;
|
||||||
const field_access_type = analyzer.module.types.array.get(field_access_type_index);
|
const field_access_type = analyzer.module.types.array.get(field_access_type_index);
|
||||||
@ -723,6 +724,15 @@ const Analyzer = struct {
|
|||||||
};
|
};
|
||||||
break :b try analyzer.processCallToFunctionPrototype(scope_index, function_prototype_index, call_argument_node_list.items, method_object);
|
break :b try analyzer.processCallToFunctionPrototype(scope_index, function_prototype_index, call_argument_node_list.items, method_object);
|
||||||
},
|
},
|
||||||
|
.function_declaration => |function_index| {
|
||||||
|
const function_declaration = analyzer.module.types.function_declarations.get(function_index);
|
||||||
|
const function_prototype_index = analyzer.module.types.array.get(function_declaration.prototype).function;
|
||||||
|
// TODO:
|
||||||
|
assert(!is_field_access);
|
||||||
|
const method_object = Value.Index.invalid;
|
||||||
|
|
||||||
|
break :b try analyzer.processCallToFunctionPrototype(scope_index, function_prototype_index, call_argument_node_list.items, method_object);
|
||||||
|
},
|
||||||
.field_access => |field_access_index| {
|
.field_access => |field_access_index| {
|
||||||
const field_access = analyzer.module.values.field_accesses.get(field_access_index);
|
const field_access = analyzer.module.values.field_accesses.get(field_access_index);
|
||||||
const container_field = analyzer.module.types.container_fields.get(field_access.field);
|
const container_field = analyzer.module.types.container_fields.get(field_access.field);
|
||||||
@ -1693,7 +1703,10 @@ const Analyzer = struct {
|
|||||||
const function_prototype = analyzer.module.types.array.get(function_definition.prototype);
|
const function_prototype = analyzer.module.types.array.get(function_definition.prototype);
|
||||||
const return_type_index = analyzer.functionPrototypeReturnType(function_prototype.function);
|
const return_type_index = analyzer.functionPrototypeReturnType(function_prototype.function);
|
||||||
logln(.sema, .fn_return_type, "Function {s} has return type #{}", .{ analyzer.module.getName(declaration.name).?, return_type_index.uniqueInteger() });
|
logln(.sema, .fn_return_type, "Function {s} has return type #{}", .{ analyzer.module.getName(declaration.name).?, return_type_index.uniqueInteger() });
|
||||||
try analyzer.module.map.functions.put(analyzer.allocator, function_index, declaration_index);
|
try analyzer.module.map.function_definitions.put(analyzer.allocator, function_index, declaration_index);
|
||||||
|
},
|
||||||
|
.function_declaration => |function_index| {
|
||||||
|
try analyzer.module.map.function_declarations.put(analyzer.allocator, function_index, declaration_index);
|
||||||
},
|
},
|
||||||
.type => |type_index| {
|
.type => |type_index| {
|
||||||
try analyzer.module.map.types.put(analyzer.allocator, type_index, declaration_index);
|
try analyzer.module.map.types.put(analyzer.allocator, type_index, declaration_index);
|
||||||
@ -1880,17 +1893,10 @@ const Analyzer = struct {
|
|||||||
},
|
},
|
||||||
.compiler_intrinsic => try analyzer.compilerIntrinsic(scope_index, expect_type, node_index),
|
.compiler_intrinsic => try analyzer.compilerIntrinsic(scope_index, expect_type, node_index),
|
||||||
.function_definition => blk: {
|
.function_definition => blk: {
|
||||||
const function_scope_index = try analyzer.module.values.scopes.append(analyzer.allocator, .{
|
const function_prototype_index = try analyzer.functionPrototype(scope_index, node.left);
|
||||||
.parent = scope_index,
|
|
||||||
.file = analyzer.module.values.scopes.get(scope_index).file,
|
|
||||||
.token = node.token,
|
|
||||||
});
|
|
||||||
|
|
||||||
logln(.sema, .type, "Creating function scope #{}. Parent #{}", .{ function_scope_index.uniqueInteger(), scope_index.uniqueInteger() });
|
|
||||||
|
|
||||||
const function_prototype_index = try analyzer.functionPrototype(function_scope_index, node.left);
|
|
||||||
const function_prototype = analyzer.module.types.function_prototypes.get(function_prototype_index);
|
const function_prototype = analyzer.module.types.function_prototypes.get(function_prototype_index);
|
||||||
assert(!function_prototype.attributes.@"extern");
|
assert(!function_prototype.attributes.@"extern");
|
||||||
|
const function_scope_index = function_prototype.scope;
|
||||||
|
|
||||||
const expected_type = ExpectType{
|
const expected_type = ExpectType{
|
||||||
.type_index = analyzer.functionPrototypeReturnType(function_prototype_index),
|
.type_index = analyzer.functionPrototypeReturnType(function_prototype_index),
|
||||||
@ -1904,7 +1910,6 @@ const Analyzer = struct {
|
|||||||
const function_index = try analyzer.module.types.function_definitions.append(analyzer.allocator, .{
|
const function_index = try analyzer.module.types.function_definitions.append(analyzer.allocator, .{
|
||||||
.prototype = prototype_type_index,
|
.prototype = prototype_type_index,
|
||||||
.body = function_body,
|
.body = function_body,
|
||||||
.scope = function_scope_index,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = Value{
|
const result = Value{
|
||||||
@ -1924,7 +1929,6 @@ const Analyzer = struct {
|
|||||||
const function_declaration_index = try analyzer.module.types.function_declarations.append(analyzer.allocator, .{
|
const function_declaration_index = try analyzer.module.types.function_declarations.append(analyzer.allocator, .{
|
||||||
.prototype = prototype_type_index,
|
.prototype = prototype_type_index,
|
||||||
.body = Block.Index.invalid,
|
.body = Block.Index.invalid,
|
||||||
.scope = Scope.Index.invalid,
|
|
||||||
});
|
});
|
||||||
break :b Value{
|
break :b Value{
|
||||||
.function_declaration = function_declaration_index,
|
.function_declaration = function_declaration_index,
|
||||||
@ -1933,7 +1937,6 @@ const Analyzer = struct {
|
|||||||
false => unreachable,
|
false => unreachable,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
.simple_while => unreachable,
|
|
||||||
.block => blk: {
|
.block => blk: {
|
||||||
const block_index = try analyzer.block(scope_index, expect_type, node_index);
|
const block_index = try analyzer.block(scope_index, expect_type, node_index);
|
||||||
break :blk Value{
|
break :blk Value{
|
||||||
@ -3077,12 +3080,18 @@ const Analyzer = struct {
|
|||||||
return type_index;
|
return type_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn processSimpleFunctionPrototype(analyzer: *Analyzer, scope_index: Scope.Index, simple_function_prototype_node_index: Node.Index) !Function.Prototype {
|
fn processSimpleFunctionPrototype(analyzer: *Analyzer, old_scope_index: Scope.Index, simple_function_prototype_node_index: Node.Index) !Function.Prototype {
|
||||||
const simple_function_prototype_node = analyzer.getScopeNode(scope_index, simple_function_prototype_node_index);
|
const simple_function_prototype_node = analyzer.getScopeNode(old_scope_index, simple_function_prototype_node_index);
|
||||||
assert(simple_function_prototype_node.id == .simple_function_prototype);
|
assert(simple_function_prototype_node.id == .simple_function_prototype);
|
||||||
const arguments_node_index = simple_function_prototype_node.left;
|
const arguments_node_index = simple_function_prototype_node.left;
|
||||||
const return_type_node_index = simple_function_prototype_node.right;
|
const return_type_node_index = simple_function_prototype_node.right;
|
||||||
|
|
||||||
|
const scope_index = try analyzer.module.values.scopes.append(analyzer.allocator, .{
|
||||||
|
.parent = old_scope_index,
|
||||||
|
.file = analyzer.module.values.scopes.get(old_scope_index).file,
|
||||||
|
.token = simple_function_prototype_node.token,
|
||||||
|
});
|
||||||
|
|
||||||
var argument_declarations = ArrayList(Declaration.Index){};
|
var argument_declarations = ArrayList(Declaration.Index){};
|
||||||
switch (arguments_node_index.invalid) {
|
switch (arguments_node_index.invalid) {
|
||||||
true => {},
|
true => {},
|
||||||
@ -3128,6 +3137,7 @@ const Analyzer = struct {
|
|||||||
return .{
|
return .{
|
||||||
.arguments = argument_declarations,
|
.arguments = argument_declarations,
|
||||||
.return_type = return_type,
|
.return_type = return_type,
|
||||||
|
.scope = scope_index,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3149,8 +3159,14 @@ const Analyzer = struct {
|
|||||||
const attribute_node = analyzer.getScopeNode(scope_index, attribute_node_index);
|
const attribute_node = analyzer.getScopeNode(scope_index, attribute_node_index);
|
||||||
|
|
||||||
switch (attribute_node.id) {
|
switch (attribute_node.id) {
|
||||||
.extern_qualifier => function_prototype.attributes.@"extern" = true,
|
|
||||||
.export_qualifier => function_prototype.attributes.@"export" = true,
|
.export_qualifier => function_prototype.attributes.@"export" = true,
|
||||||
|
.extern_qualifier => {
|
||||||
|
const string_literal_node = analyzer.getScopeNode(scope_index, attribute_node.left);
|
||||||
|
const original_string_literal = analyzer.tokenStringLiteral(scope_index, string_literal_node.token);
|
||||||
|
const fixed_string_literal = try fixupStringLiteral(analyzer.allocator, original_string_literal);
|
||||||
|
_ = try analyzer.module.map.libraries.getOrPut(analyzer.allocator, fixed_string_literal);
|
||||||
|
function_prototype.attributes.@"extern" = true;
|
||||||
|
},
|
||||||
.calling_convention => {
|
.calling_convention => {
|
||||||
const calling_convention_type_declaration = try analyzer.forceDeclarationAnalysis(scope_index, "std.builtin.CallingConvention");
|
const calling_convention_type_declaration = try analyzer.forceDeclarationAnalysis(scope_index, "std.builtin.CallingConvention");
|
||||||
const calling_convention_type = switch (analyzer.module.values.array.get(calling_convention_type_declaration).*) {
|
const calling_convention_type = switch (analyzer.module.values.array.get(calling_convention_type_declaration).*) {
|
||||||
|
@ -384,13 +384,22 @@ const Analyzer = struct {
|
|||||||
.left_brace,
|
.left_brace,
|
||||||
=> break,
|
=> break,
|
||||||
.fixed_keyword_extern => b: {
|
.fixed_keyword_extern => b: {
|
||||||
const result = try analyzer.addNode(.{
|
analyzer.consumeToken();
|
||||||
.id = .extern_qualifier,
|
_ = try analyzer.expectToken(.left_parenthesis);
|
||||||
.token = attribute_token,
|
const string_literal = try analyzer.addNode(.{
|
||||||
|
.id = .string_literal,
|
||||||
|
.token = try analyzer.expectToken(.string_literal),
|
||||||
.left = Node.Index.invalid,
|
.left = Node.Index.invalid,
|
||||||
.right = Node.Index.invalid,
|
.right = Node.Index.invalid,
|
||||||
});
|
});
|
||||||
analyzer.consumeToken();
|
_ = try analyzer.expectToken(.right_parenthesis);
|
||||||
|
|
||||||
|
const result = try analyzer.addNode(.{
|
||||||
|
.id = .extern_qualifier,
|
||||||
|
.token = attribute_token,
|
||||||
|
.left = string_literal,
|
||||||
|
.right = Node.Index.invalid,
|
||||||
|
});
|
||||||
break :b result;
|
break :b result;
|
||||||
},
|
},
|
||||||
.fixed_keyword_export => b: {
|
.fixed_keyword_export => b: {
|
||||||
@ -1391,6 +1400,7 @@ const Analyzer = struct {
|
|||||||
.right_parenthesis,
|
.right_parenthesis,
|
||||||
.left_brace,
|
.left_brace,
|
||||||
.equal,
|
.equal,
|
||||||
|
.fixed_keyword_extern,
|
||||||
=> return node_index,
|
=> return node_index,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user