aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-03 20:51:22 +0200
committerEugen Wissner <belka@caraus.de>2026-10-03 20:51:22 +0200
commite4ce7f658741a7428597da4872435a1b0bae944c (patch)
tree50f65abf6fa4468db7bc93a6ae61d623a2dd8566
parent5d808dd4c4003968bbdf180e1e1193231db5d43b (diff)
downloadelna-e4ce7f658741a7428597da4872435a1b0bae944c.tar.gz
Rework generics for parameters to be plain types
-rw-r--r--boot/symbol.cc1
-rw-r--r--boot/type_check.cc102
-rw-r--r--gcc/gcc/elna-builtins.cc6
-rw-r--r--include/elna/boot/symbol.h8
-rw-r--r--include/elna/boot/type_check.h15
-rw-r--r--source/command_line_interface.elna2
-rw-r--r--source/common.elna6
-rw-r--r--source/cstdio.elna10
-rw-r--r--source/cstdlib.elna8
-rw-r--r--source/cstring.elna6
-rw-r--r--source/lexer.elna6
-rw-r--r--source/main.elna196
-rw-r--r--testsuite/compilable/generic_alias.elna10
-rw-r--r--testsuite/compilable/generic_arguments.elna18
-rw-r--r--testsuite/compilable/generic_base_chain.elna14
-rw-r--r--testsuite/compilable/generic_const_inference.elna4
-rw-r--r--testsuite/compilable/generic_inference.elna10
-rw-r--r--testsuite/compilable/generic_pointee.elna17
-rw-r--r--testsuite/fail_compilation/generic_arity.elna2
-rw-r--r--testsuite/fail_compilation/generic_base_mismatch.elna10
-rw-r--r--testsuite/fail_compilation/generic_by_value.elna7
-rw-r--r--testsuite/fail_compilation/generic_field_by_value.elna8
-rw-r--r--testsuite/fail_compilation/generic_parameter_arithmetic.elna5
-rw-r--r--testsuite/fail_compilation/generic_uninferrable.elna2
-rw-r--r--testsuite/runnable/generic_base.elna14
-rw-r--r--testsuite/runnable/generic_constructor.elna6
-rw-r--r--testsuite/runnable/generic_erasure.elna12
-rw-r--r--testsuite/runnable/generic_record.elna8
28 files changed, 281 insertions, 232 deletions
diff --git a/boot/symbol.cc b/boot/symbol.cc
index e247bdb..4828070 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -809,7 +809,6 @@ namespace elna::boot
{
return checked.get<pointer_type>() != nullptr
|| checked.get<procedure_type>() != nullptr
- || checked.get<parameter_type>() != nullptr
|| is_primitive_type(checked, "Pointer");
}
diff --git a/boot/type_check.cc b/boot/type_check.cc
index 42e7227..82c910f 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -137,11 +137,6 @@ namespace elna::boot
return "Type parameter '" + payload.parameter + "' of '"
+ this->generic_name + "' is not used";
}
- else if constexpr (std::is_same_v<T, argument_not_pointer>)
- {
- return "Type '" + payload.actual.to_string() + "' cannot be a type argument of '"
- + this->generic_name + "', it is not a pointer type";
- }
else if constexpr (std::is_same_v<T, argument_not_scalar>)
{
return "Type '" + payload.actual.to_string() + "' cannot be a type argument of '"
@@ -379,7 +374,10 @@ namespace elna::boot
*/
static std::optional<type> find_opaque_type(const type& checked)
{
- if (resolve_underlying_type(checked).get<extern_type>() != nullptr)
+ const type underlying = resolve_underlying_type(checked);
+
+ if (underlying.get<extern_type>() != nullptr
+ || underlying.get<parameter_type>() != nullptr)
{
return checked;
}
@@ -935,27 +933,59 @@ namespace elna::boot
const std::shared_ptr<alias_type> unresolved_type =
this->bag.lookup(declaration->identifier.name())->is_type()->symbol.get<alias_type>();
- if (const auto generic = unresolved_type->referent.get<generic_type>())
+ type referent = unresolved_type->referent;
+ if (const auto generic = referent.get<generic_type>())
{
check_parameters_used(declaration->position(), declaration->identifier.name(),
generic->parameters, generic->referent);
- return;
+ referent = generic->referent;
}
- const type referent = resolve_aliases(unresolved_type->referent);
+ referent = resolve_aliases(referent);
if (const auto record = referent.get<record_type>())
{
- for (const auto& [field_name, field] : record->fields)
+ const record_type_expression *record_expression = declaration->underlying_type().is_record();
+
+ if (record_expression != nullptr)
{
- if (const auto opaque = find_opaque_type(field.field_type))
+ for (const field_declaration& field : record_expression->fields)
{
- add_error<type_requirement_error>(declaration->position(),
- opaque.value(), type_requirement_error::kind::opaque_field);
+ if (field.first.empty())
+ {
+ continue;
+ }
+ const auto field_entry = record->fields.find(field.first.front().name());
+
+ if (field_entry == record->fields.end())
+ {
+ continue;
+ }
+ if (const auto opaque = find_opaque_type(field_entry->second.field_type))
+ {
+ add_error<type_requirement_error>(field.second->position(),
+ opaque.value(), type_requirement_error::kind::opaque_field);
+ }
+ else if (has_zero_size(field_entry->second.field_type, this->target))
+ {
+ add_error<type_requirement_error>(field.second->position(),
+ field_entry->second.field_type, type_requirement_error::kind::zero_sized);
+ }
}
- else if (has_zero_size(field.field_type, this->target))
+ }
+ else
+ {
+ for (const auto& [field_name, field] : record->fields)
{
- add_error<type_requirement_error>(declaration->position(),
- field.field_type, type_requirement_error::kind::zero_sized);
+ if (const auto opaque = find_opaque_type(field.field_type))
+ {
+ add_error<type_requirement_error>(declaration->position(),
+ opaque.value(), type_requirement_error::kind::opaque_field);
+ }
+ else if (has_zero_size(field.field_type, this->target))
+ {
+ add_error<type_requirement_error>(declaration->position(),
+ field.field_type, type_requirement_error::kind::zero_sized);
+ }
}
}
}
@@ -1137,10 +1167,17 @@ namespace elna::boot
}
else if (const auto left_pointer = left.get<pointer_type>())
{
- const std::shared_ptr<pointer_type> right_pointer = right.get<pointer_type>();
+ if (is_primitive_type(right, "Pointer"))
+ {
+ return true;
+ }
+ else
+ {
+ const std::shared_ptr<pointer_type> right_pointer = right.get<pointer_type>();
- return right_pointer != nullptr
- && bind_arguments(parameters, bindings, left_pointer->base, right_pointer->base);
+ return right_pointer != nullptr
+ && bind_arguments(parameters, bindings, left_pointer->base, right_pointer->base);
+ }
}
else if (const auto left_slice = left.get<slice_type>())
{
@@ -1227,7 +1264,7 @@ namespace elna::boot
{
return argument_rule::mutable_scalar;
}
- return argument_rule::pointer;
+ return argument_rule::opaque;
}
void type_analysis_visitor::check_arguments(const named_expression& reference,
@@ -1241,18 +1278,13 @@ namespace elna::boot
}
const type underlying = resolve_underlying_type(argument);
- if (rule != argument_rule::scalar
+ if (rule == argument_rule::mutable_scalar
&& resolve_aliases(argument).get<constant_type>() != nullptr)
{
add_error<generic_error>(reference.position(), reference.name,
generic_error::constant_argument{ argument });
}
- else if (rule == argument_rule::pointer && !is_any_pointer_type(underlying))
- {
- add_error<generic_error>(reference.position(), reference.name,
- generic_error::argument_not_pointer{ argument });
- }
- else if (rule != argument_rule::pointer && !is_scalar_type(underlying))
+ else if (rule != argument_rule::opaque && !is_scalar_type(underlying))
{
add_error<generic_error>(reference.position(), reference.name,
generic_error::argument_not_scalar{ argument });
@@ -1308,7 +1340,7 @@ namespace elna::boot
}
else
{
- check_arguments(*expression, expression->argument_types, argument_rule::pointer);
+ check_arguments(*expression, expression->argument_types, argument_rule::opaque);
}
}
else if (std::shared_ptr<generic_type> const generic = unwrap_generic(denoted))
@@ -1619,12 +1651,18 @@ namespace elna::boot
const type resolved_base = resolve_underlying_type(expression->base().type_decoration);
- if (resolved_base.get<parameter_type>() != nullptr)
+ if (const auto pointer = resolved_base.get<pointer_type>())
{
- add_error<type_requirement_error>(expression->position(), expression->base().type_decoration,
- type_requirement_error::kind::dereference_of_parameter);
+ if (const auto opaque = find_opaque_type(pointer->base))
+ {
+ if (opaque->get<parameter_type>() != nullptr)
+ {
+ add_error<type_requirement_error>(expression->position(), *opaque,
+ type_requirement_error::kind::dereference_of_parameter);
+ }
+ }
}
- else if (resolved_base.get<pointer_type>() == nullptr)
+ else
{
add_error<type_requirement_error>(expression->position(), expression->base().type_decoration,
type_requirement_error::kind::dereference_of_non_pointer);
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index fc43ebe..643b988 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -266,6 +266,10 @@ namespace elna::gcc
}
else if (const auto reference = type.get<boot::pointer_type>())
{
+ if (boot::resolve_underlying_type(reference->base).get<boot::parameter_type>() != nullptr)
+ {
+ return elna_pointer_type_node;
+ }
return build_pointer_type(get_inner_alias(reference->base, symbols, placeholder));
}
else if (const auto reference = type.get<boot::array_type>())
@@ -304,7 +308,7 @@ namespace elna::gcc
}
else if (type.get<boot::parameter_type>() != nullptr)
{
- return elna_pointer_type_node;
+ return error_mark_node;
}
else if (const auto reference = type.get<boot::instantiated_type>())
{
diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h
index 31d5c45..705cb29 100644
--- a/include/elna/boot/symbol.h
+++ b/include/elna/boot/symbol.h
@@ -225,10 +225,10 @@ namespace elna::boot
/**
* Type parameter of a generic declaration.
*
- * It denotes an unknown pointer type chosen at instantiation, so it is
- * usable wherever a pointer is, and erases to a pointer in the backend.
- * Each declaration gets fresh parameters; two parameters spelled alike in
- * different declarations never compare equal.
+ * It denotes an unknown opaque type chosen at instantiation, so it is
+ * usable only behind a pointer (^T), and ^T erases to a pointer in the
+ * backend. Each declaration gets fresh parameters; two parameters spelled
+ * alike in different declarations never compare equal.
*/
struct parameter_type
{
diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h
index 5e4f792..5a2d7f1 100644
--- a/include/elna/boot/type_check.h
+++ b/include/elna/boot/type_check.h
@@ -177,10 +177,6 @@ namespace elna::boot
{
std::string parameter;
};
- struct argument_not_pointer
- {
- type actual;
- };
struct argument_not_scalar
{
type actual;
@@ -200,7 +196,7 @@ namespace elna::boot
};
using payload_type = std::variant<not_generic, unused_parameter,
- argument_not_pointer, argument_not_scalar, constant_argument,
+ argument_not_scalar, constant_argument,
uninferrable_parameter, shape_mismatch>;
generic_error(const source_position position, const std::string& generic_name,
@@ -216,14 +212,13 @@ namespace elna::boot
/**
* What a generic declaration accepts as a type argument.
*
- * An erased generic takes a pointer, because that is what its single
- * compiled body knows how to move. A builtin has no body to erase, so it
- * takes whatever it can load or store, and only a reading one tolerates a
- * constant.
+ * An erased generic takes an opaque pointee, because it is only used
+ * behind a pointer. A builtin has no body to erase, so it takes whatever
+ * it can load or store, and only a reading one tolerates a constant.
*/
enum class argument_rule
{
- pointer,
+ opaque,
scalar,
mutable_scalar
};
diff --git a/source/command_line_interface.elna b/source/command_line_interface.elna
index 511d6a0..1318e67 100644
--- a/source/command_line_interface.elna
+++ b/source/command_line_interface.elna
@@ -23,7 +23,7 @@ var
parsed: Bool
begin
i := 1;
- result := malloc(#size(CommandLine));
+ result := malloc#[CommandLine](#size(CommandLine));
result^.lex := false;
result^.parse := false;
result^.input := nil;
diff --git a/source/common.elna b/source/common.elna
index 4579a67..428c4ec 100644
--- a/source/common.elna
+++ b/source/common.elna
@@ -14,15 +14,15 @@ type
end_location: ElnaLocation
end
-proc write*(fd: Int; buf: Pointer; Word: Int) -> Int
+proc write*#[T](fd: Int; buf: ^const T; size: Word) -> Int
extern
proc write_s*(value: []const Word8)
- write(1, cast(value.ptr: Pointer), cast(value.length: Int))
+ write(1, value.ptr, value.length)
return
proc write_z*(value: ^Word8)
- write(1, cast(value: Pointer), cast(strlen(value): Int))
+ write(1, value, strlen(value))
return
proc write_b*(value: Bool)
diff --git a/source/cstdio.elna b/source/cstdio.elna
index e69d81a..928c7e1 100644
--- a/source/cstdio.elna
+++ b/source/cstdio.elna
@@ -29,10 +29,10 @@ extern
proc fflush*(stream: ^FILE) -> Int
extern
-proc fread*(ptr: Pointer; size: Word; nmemb: Word; stream: ^FILE) -> Word
+proc fread*#[T](ptr: ^T; size: Word; nmemb: Word; stream: ^FILE) -> Word
extern
-proc fwrite*(ptr: const Pointer; size: Word; nitems: Word; stream: ^FILE) -> Word
+proc fwrite*#[T](ptr: ^const T; size: Word; nitems: Word; stream: ^FILE) -> Word
extern
proc fputc*(c: Int; stream: ^FILE) -> Word
@@ -47,13 +47,13 @@ extern
proc putchar*(c: Int) -> Int
extern
-proc sprintf*(str: Pointer; format: ^const Word8; number: Word) -> Int
+proc sprintf*(str: ^Word8; format: ^const Word8) #{varargs} -> Int
extern
-proc fprintf*(stream: Pointer; format: ^const Word8; number: Word) -> Int
+proc fprintf*(stream: ^FILE; format: ^const Word8) #{varargs} -> Int
extern
-proc fdopen*(fildes: Int; mode: ^const Word8) -> Pointer
+proc fdopen*(fildes: Int; mode: ^const Word8) -> ^FILE
extern
end.
diff --git a/source/cstdlib.elna b/source/cstdlib.elna
index 51f8ea0..10a4d80 100644
--- a/source/cstdlib.elna
+++ b/source/cstdlib.elna
@@ -3,16 +3,16 @@
obtain one at https://mozilla.org/MPL/2.0/. *)
module
-proc malloc*(size: Word) -> Pointer
+proc malloc*#[T](size: Word) -> ^T
extern
-proc free*(ptr: Pointer)
+proc free*#[T](ptr: ^T)
extern
-proc calloc*(nmemb: Word; size: Word) -> Pointer
+proc calloc*#[T](nmemb: Word; size: Word) -> ^T
extern
-proc realloc*(ptr: Pointer; size: Word) -> Pointer
+proc realloc*#[T](ptr: ^T; size: Word) -> ^T
extern
proc atoi*(str: ^Word8) -> Int
diff --git a/source/cstring.elna b/source/cstring.elna
index dcf9e6f..3973573 100644
--- a/source/cstring.elna
+++ b/source/cstring.elna
@@ -3,13 +3,13 @@
obtain one at https://mozilla.org/MPL/2.0/. *)
module
-proc memset*(ptr: Pointer; c: Int; n: Word) -> ^Word8
+proc memset*#[T](ptr: ^T; c: Int; n: Word) -> ^Word8
extern
-proc memcpy*(dst: Pointer; src: const Pointer; n: Word)
+proc memcpy*#[T](dst: ^T; src: ^const T; n: Word)
extern
-proc memcmp*(s1, s2: const Pointer; n: Word) -> Int
+proc memcmp*#[T](s1, s2: ^const T; n: Word) -> Int
extern
proc strcmp*(s1: ^const Word8; s2: ^const Word8) -> Int
diff --git a/source/lexer.elna b/source/lexer.elna
index bf1c449..370c24d 100644
--- a/source/lexer.elna
+++ b/source/lexer.elna
@@ -528,7 +528,7 @@ proc elna_lexer_token_create(kind: ElnaLexerKind; position: ^ElnaPosition) -> ^E
var
result: ^ElnaLexerToken
begin
- result := malloc(#size(ElnaLexerToken));
+ result := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
result^.kind := kind;
result^.position := position^
return result
@@ -640,7 +640,7 @@ var
character: Word8
result: ^ElnaLexerToken
begin
- result := malloc(#size(ElnaLexerToken));
+ result := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
character := start_position^;
if character = ';' then
@@ -722,7 +722,7 @@ begin
token := elna_lexer_classify_single(cursor^.start, @cursor^.position)
elsif action_to_perform = ElnaLexerAction.eof then
- token := malloc(#size(ElnaLexerToken));
+ token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
token^.kind := ElnaLexerKind.eof
elsif action_to_perform = ElnaLexerAction.finalize then
token := elna_lexer_classify_finalize(cursor^.start, @cursor^.position)
diff --git a/source/main.elna b/source/main.elna
index adac5ac..26853c3 100644
--- a/source/main.elna
+++ b/source/main.elna
@@ -14,17 +14,17 @@ type
index: Word
end
StringBuffer* = record
- data: Pointer;
+ data: ^Word8;
size: Word;
capacity: Word
end
- SourceCode = record
+ SourceCode#[T] = record
position: ElnaLocation;
- input: Pointer;
- empty: proc(stream: Pointer) -> Bool;
- advance: proc(stream: Pointer);
- head: proc(stream: Pointer) -> Word8
+ input: ^T;
+ empty: proc(stream: ^T) -> Bool;
+ advance: proc(stream: ^T);
+ head: proc(stream: ^T) -> Word8
end
Tokenizer* = record
length: Word;
@@ -34,14 +34,11 @@ type
(*
Standard procedures.
*)
-proc reallocarray(ptr: Pointer; n: Word; size: Word) -> Pointer
-return realloc(ptr, n * size)
-
proc string_dup(origin: []const Word8) -> []const Word8
var
copy: ^Word8
begin
- copy := malloc(origin.length);
+ copy := malloc#[Word8](origin.length);
strncpy(copy, origin.ptr, origin.length)
return copy[1 to origin.length]
@@ -50,7 +47,7 @@ var
result: StringBuffer
begin
result.capacity := 64u;
- result.data := malloc(result.capacity);
+ result.data := malloc#[Word8](result.capacity);
result.size := 0u
return result
@@ -89,60 +86,46 @@ begin
file_handle := fopen(filename, "rb\0".ptr);
if file_handle <> nil then
- result := malloc(#size(SourceFile));
+ result := malloc#[SourceFile](#size(SourceFile));
result^.handle := file_handle;
result^.size := 0u;
result^.index := 1u
end
return result
-proc source_file_empty(source_input: Pointer) -> Bool
-var
- source_file: ^SourceFile
-begin
- source_file := cast(source_input: ^SourceFile);
-
- if source_file^.index > source_file^.size then
- source_file^.size := fread(cast(@source_file^.buffer: Pointer), 1u, 1024u, source_file^.handle);
- source_file^.index := 1u
+proc source_file_empty(source_input: ^SourceFile) -> Bool
+ if source_input^.index > source_input^.size then
+ source_input^.size := fread(source_input^.buffer.ptr, 1u, 1024u, source_input^.handle);
+ source_input^.index := 1u
end
-return source_file^.size = 0u
+return source_input^.size = 0u
-proc source_file_head(source_input: Pointer) -> Word8
-var
- source_file: ^SourceFile
-begin
- source_file := cast(source_input: ^SourceFile)
-return source_file^.buffer[source_file^.index]
-
-proc source_file_advance(source_input: Pointer)
-var
- source_file: ^SourceFile
-begin
- source_file := cast(source_input: ^SourceFile);
+proc source_file_head(source_input: ^SourceFile) -> Word8
+return source_input^.buffer[source_input^.index]
- source_file^.index := source_file^.index + 1u
+proc source_file_advance(source_input: ^SourceFile)
+ source_input^.index := source_input^.index + 1u
return
-proc source_code_empty(source_code: ^SourceCode) -> Bool
+proc source_code_empty#[T](source_code: ^SourceCode#[T]) -> Bool
return source_code^.empty(source_code^.input)
-proc source_code_head(source_code: SourceCode) -> Word8
+proc source_code_head#[T](source_code: SourceCode#[T]) -> Word8
return source_code.head(source_code.input)
-proc source_code_advance(source_code: ^SourceCode)
+proc source_code_advance#[T](source_code: ^SourceCode#[T])
begin
source_code^.advance(source_code^.input);
source_code^.position.column := source_code^.position.column
return
-proc source_code_break(source_code: ^SourceCode)
+proc source_code_break#[T](source_code: ^SourceCode#[T])
begin
source_code^.position.line := source_code^.position.line + 1u;
source_code^.position.column := 0u
return
-proc source_code_expect(source_code: ^SourceCode; expected: Word8) -> Bool
+proc source_code_expect#[T](source_code: ^SourceCode#[T]; expected: Word8) -> Bool
return ~source_code_empty(source_code) & source_code_head(source_code^) = expected
(*
@@ -187,7 +170,7 @@ begin
return successful
(* Skip spaces. *)
-proc lexer_spaces(source_code: ^SourceCode)
+proc lexer_spaces#[T](source_code: ^SourceCode#[T])
var
current: Word8
begin
@@ -205,7 +188,7 @@ return
proc lexer_is_ident(char: Word8) -> Bool
return isalnum(cast(char: Int)) <> 0 or char = '_'
-proc lexer_identifier(source_code: ^SourceCode; token_content: ^StringBuffer)
+proc lexer_identifier#[T](source_code: ^SourceCode#[T]; token_content: ^StringBuffer)
var
content_length: Word
begin
@@ -215,7 +198,7 @@ begin
end
return
-proc lexer_comment(source_code: ^SourceCode; token_content: ^StringBuffer) -> Bool
+proc lexer_comment#[T](source_code: ^SourceCode#[T]; token_content: ^StringBuffer) -> Bool
var
trailing: Word
begin
@@ -236,7 +219,7 @@ begin
end
return trailing = 2u
-proc lexer_character(source_code: ^SourceCode; token_content: ^Word8) -> Bool
+proc lexer_character#[T](source_code: ^SourceCode#[T]; token_content: ^Word8) -> Bool
var
successful: Bool
begin
@@ -257,7 +240,7 @@ begin
end
return successful
-proc lexer_string(source_code: ^SourceCode; token_content: ^StringBuffer) -> Bool
+proc lexer_string#[T](source_code: ^SourceCode#[T]; token_content: ^StringBuffer) -> Bool
var
token_end, constructed_string: ^Word8
token_length: Word
@@ -279,7 +262,7 @@ begin
end
return is_valid
-proc lexer_number(source_code: ^SourceCode; token_content: ^Int)
+proc lexer_number#[T](source_code: ^SourceCode#[T]; token_content: ^Int)
begin
token_content^ := 0;
@@ -296,81 +279,81 @@ var
current_token: ^ElnaLexerToken
begin
if token_content = "if" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._if
elsif token_content = "then" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._then
elsif token_content = "else" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._else
elsif token_content = "elsif" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._elsif
elsif token_content = "while" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._while
elsif token_content = "do" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._do
elsif token_content = "proc" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._proc
elsif token_content = "begin" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._begin
elsif token_content = "end" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._end
elsif token_content = "extern" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._extern
elsif token_content = "const" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._const
elsif token_content = "var" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._var
elsif token_content = "case" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._case
elsif token_content = "of" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._of
elsif token_content = "type" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._type
elsif token_content = "record" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._record
elsif token_content = "true" then
- current_token := malloc(#size(ElnaLexerBooleanToken));
+ current_token := malloc#[ElnaLexerBooleanToken](#size(ElnaLexerBooleanToken));
current_token^.kind := ElnaLexerKind.boolean;
cast(current_token: ^ElnaLexerBooleanToken)^.value := true
elsif token_content = "false" then
- current_token := malloc(#size(ElnaLexerBooleanToken));
+ current_token := malloc#[ElnaLexerBooleanToken](#size(ElnaLexerBooleanToken));
current_token^.kind := ElnaLexerKind.boolean;
cast(current_token: ^ElnaLexerBooleanToken)^.value := false
elsif token_content = "nil" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.null
elsif token_content = "or" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._or
elsif token_content = "return" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._return
elsif token_content = "cast" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._cast
elsif token_content = "defer" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._defer
elsif token_content = "import" then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind._import
else
- current_token := malloc(#size(ElnaLexerStringToken));
+ current_token := malloc#[ElnaLexerStringToken](#size(ElnaLexerStringToken));
current_token^.kind := ElnaLexerKind.identifier;
cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(token_content)
end
@@ -381,13 +364,13 @@ var
new_length: Word
begin
new_length := lexer^.length + 1u;
- lexer^.data := cast(reallocarray(cast(lexer^.data: Pointer), new_length, #size(Pointer)): ^^ElnaLexerToken);
+ lexer^.data := realloc#[^ElnaLexerToken](lexer^.data, new_length * #size(^ElnaLexerToken));
(lexer^.data + lexer^.length)^ := token;
lexer^.length := new_length
return
(* Read the next token from the input. *)
-proc lexer_next(source_code: SourceCode; token_buffer: ^StringBuffer) -> ^ElnaLexerToken
+proc lexer_next#[T](source_code: SourceCode#[T]; token_buffer: ^StringBuffer) -> ^ElnaLexerToken
var
current_token: ^ElnaLexerToken := nil
first_char: Word8
@@ -401,11 +384,11 @@ begin
source_code_advance(@source_code);
lexer_identifier(@source_code, token_buffer);
- current_token := malloc(#size(ElnaLexerStringToken));
+ current_token := malloc#[ElnaLexerStringToken](#size(ElnaLexerStringToken));
current_token^.kind := ElnaLexerKind.trait;
cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(string_buffer_clear(token_buffer))
elsif isdigit(cast(first_char: Int)) <> 0 then
- current_token := malloc(#size(ElnaLexerIntegerToken));
+ current_token := malloc#[ElnaLexerIntegerToken](#size(ElnaLexerIntegerToken));
lexer_number(@source_code, @cast(current_token: ^ElnaLexerIntegerToken)^.value);
if source_code_expect(@source_code, 'u') then
@@ -418,37 +401,37 @@ begin
source_code_advance(@source_code);
if source_code_empty(@source_code) then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.left_paren
elsif source_code_head(source_code) = '*' then
source_code_advance(@source_code);
if lexer_comment(@source_code, token_buffer) then
- current_token := malloc(#size(ElnaLexerStringToken));
+ current_token := malloc#[ElnaLexerStringToken](#size(ElnaLexerStringToken));
cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(string_buffer_clear(token_buffer));
current_token^.kind := ElnaLexerKind.comment
end
else
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.left_paren
end
elsif first_char = ')' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.right_paren;
source_code_advance(@source_code)
elsif first_char = '{' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.left_brace;
source_code_advance(@source_code)
elsif first_char = '}' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.right_brace;
source_code_advance(@source_code)
elsif first_char = '\'' then
source_code_advance(@source_code);
if lexer_character(@source_code, @first_char) & source_code_expect(@source_code, '\'') then
- current_token := malloc(#size(ElnaLexerCharacterToken));
+ current_token := malloc#[ElnaLexerCharacterToken](#size(ElnaLexerCharacterToken));
current_token^.kind := ElnaLexerKind.character;
cast(current_token: ^ElnaLexerCharacterToken)^.value := first_char;
source_code_advance(@source_code)
@@ -457,21 +440,21 @@ begin
source_code_advance(@source_code);
if lexer_string(@source_code, token_buffer) then
- current_token := malloc(#size(ElnaLexerStringToken));
+ current_token := malloc#[ElnaLexerStringToken](#size(ElnaLexerStringToken));
current_token^.kind := ElnaLexerKind.string;
cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(string_buffer_clear(token_buffer))
end
elsif first_char = '[' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.left_square;
source_code_advance(@source_code)
elsif first_char = ']' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.right_square;
source_code_advance(@source_code)
elsif first_char = '>' then
source_code_advance(@source_code);
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
if source_code_empty(@source_code) then
current_token^.kind := ElnaLexerKind.greater_than
@@ -486,7 +469,7 @@ begin
end
elsif first_char = '<' then
source_code_advance(@source_code);
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
if source_code_empty(@source_code) then
current_token^.kind := ElnaLexerKind.less_than
@@ -503,28 +486,28 @@ begin
current_token^.kind := ElnaLexerKind.less_than
end
elsif first_char = '=' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.equals;
source_code_advance(@source_code)
elsif first_char = ';' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.semicolon;
source_code_advance(@source_code)
elsif first_char = '.' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.dot;
source_code_advance(@source_code)
elsif first_char = ',' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.comma;
source_code_advance(@source_code)
elsif first_char = '+' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.plus;
source_code_advance(@source_code)
elsif first_char = '-' then
source_code_advance(@source_code);
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
if source_code_empty(@source_code) then
current_token^.kind := ElnaLexerKind.minus
@@ -535,20 +518,20 @@ begin
current_token^.kind := ElnaLexerKind.minus
end
elsif first_char = '*' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.multiplication;
source_code_advance(@source_code)
elsif first_char = '/' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.division;
source_code_advance(@source_code)
elsif first_char = '%' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.remainder;
source_code_advance(@source_code)
elsif first_char = ':' then
source_code_advance(@source_code);
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
if source_code_empty(@source_code) then
current_token^.kind := ElnaLexerKind.colon
@@ -559,34 +542,34 @@ begin
current_token^.kind := ElnaLexerKind.colon
end
elsif first_char = '^' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.hat;
source_code_advance(@source_code)
elsif first_char = '@' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.at;
source_code_advance(@source_code)
elsif first_char = '!' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.exclamation;
source_code_advance(@source_code)
elsif first_char = '&' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.and;
source_code_advance(@source_code)
elsif first_char = '~' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.not;
source_code_advance(@source_code)
elsif first_char = '|' then
- current_token := malloc(#size(ElnaLexerToken));
+ current_token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
current_token^.kind := ElnaLexerKind.pipe;
source_code_advance(@source_code)
end
return current_token
(* Split the source text into tokens. *)
-proc lexer_text(source_code: SourceCode) -> Tokenizer
+proc lexer_text#[T](source_code: SourceCode#[T]) -> Tokenizer
var
current_token: ^ElnaLexerToken
token_buffer: StringBuffer
@@ -769,7 +752,7 @@ return
Compilation entry.
*)
-proc compile_in_stages(command_line: ^CommandLine; source_code: SourceCode) -> Int
+proc compile_in_stages#[T](command_line: ^CommandLine; source_code: SourceCode#[T]) -> Int
var
return_code: Int := 0
lexer: Tokenizer
@@ -786,7 +769,7 @@ proc process(argc: Int; argv: ^^Word8) -> Int
var
tokens: ^ElnaLexerToken
tokens_size: Word
- source_code: SourceCode
+ source_code: SourceCode#[SourceFile]
command_line: ^CommandLine
return_code: Int := 0
source_file: ^SourceFile
@@ -821,7 +804,6 @@ begin
return return_code
proc initialize_global_state()
-begin
stdin := fdopen(0, "r\0".ptr);
stdout := fdopen(1, "w\0".ptr);
stderr := fdopen(2, "w\0".ptr)
diff --git a/testsuite/compilable/generic_alias.elna b/testsuite/compilable/generic_alias.elna
index 47ac638..da9501a 100644
--- a/testsuite/compilable/generic_alias.elna
+++ b/testsuite/compilable/generic_alias.elna
@@ -6,7 +6,7 @@ type
Node#[T] = record
next: ^Node#[T];
- value: T
+ value: ^T
end
Ref#[T] = ^T
@@ -16,10 +16,10 @@ type
end
var
- chain: Node#[^File]
- aliased: Ref#[^File]
- raw: ^^File
- boxed: Boxed#[^File]
+ chain: Node#[File]
+ aliased: Ref#[File]
+ raw: ^File
+ boxed: Boxed#[File]
begin
chain.next := nil;
diff --git a/testsuite/compilable/generic_arguments.elna b/testsuite/compilable/generic_arguments.elna
index 4d33db5..1cda57f 100644
--- a/testsuite/compilable/generic_arguments.elna
+++ b/testsuite/compilable/generic_arguments.elna
@@ -5,22 +5,22 @@ type
end
Pair#[K, V] = record
- key: K;
- value: V
+ key: ^K;
+ value: ^V
end
var
- entry: Pair#[^File, ^Word8]
+ entry: Pair#[File, Word8]
-proc allocate#[T](size: Word) -> T
+proc allocate#[T](size: Word) -> ^T
extern
-proc first#[K, V](entry_ptr: ^Pair#[K, V]) -> K
+proc first#[K, V](entry_ptr: ^Pair#[K, V]) -> ^K
return entry_ptr^.key
begin
- entry.key := allocate#[^File](#size(File));
- assert(#size(Pair#[^File, ^Word8]) = #size(Pointer) * 2u);
- assert(#offset(Pair#[^File, ^Word8], value) = #size(Pointer));
- assert(first#[^File, ^Word8](@entry) = entry.key)
+ entry.key := allocate#[File](#size(File));
+ assert(#size(Pair#[File, Word8]) = #size(Pointer) * 2u);
+ assert(#offset(Pair#[File, Word8], value) = #size(Pointer));
+ assert(first#[File, Word8](@entry) = entry.key)
end.
diff --git a/testsuite/compilable/generic_base_chain.elna b/testsuite/compilable/generic_base_chain.elna
index c303e6d..1abe199 100644
--- a/testsuite/compilable/generic_base_chain.elna
+++ b/testsuite/compilable/generic_base_chain.elna
@@ -5,20 +5,20 @@ type
end
Map#[K, V] = record
- key: K;
- value: V
+ key: ^K;
+ value: ^V
end
- Cache#[K, V] = record(Map#[^Word8, V])
- newest: K
+ Cache#[K, V] = record(Map#[Word8, V])
+ newest: ^K
end
var
- store: Cache#[^Int, ^File]
+ store: Cache#[Int, File]
byte_key: ^Word8
- upcast: ^Map#[^Word8, ^File]
+ upcast: ^Map#[Word8, File]
-proc put#[K2, V2](target: ^Map#[K2, V2]; key: K2)
+proc put#[K2, V2](target: ^Map#[K2, V2]; key: ^K2)
begin
target^.key := key
return
diff --git a/testsuite/compilable/generic_const_inference.elna b/testsuite/compilable/generic_const_inference.elna
index a9fc41f..7ce197f 100644
--- a/testsuite/compilable/generic_const_inference.elna
+++ b/testsuite/compilable/generic_const_inference.elna
@@ -10,10 +10,10 @@ var
nested: NestedConst := nil
direct_const: const ^Word8 := nil
-proc write#[T](fd: Int; buf: T; count: Int) -> Int
+proc write#[T](fd: Int; buf: ^T; count: Int) -> Int
return 0
-proc write_const#[T](fd: Int; buf: const T; count: Int) -> Int
+proc write_const#[T](fd: Int; buf: ^const T; count: Int) -> Int
return 0
begin
diff --git a/testsuite/compilable/generic_inference.elna b/testsuite/compilable/generic_inference.elna
index 860eab1..9d7fed6 100644
--- a/testsuite/compilable/generic_inference.elna
+++ b/testsuite/compilable/generic_inference.elna
@@ -5,20 +5,20 @@ type
end
Cell#[T] = record
- held: T
+ held: ^T
end
var
- files: Cell#[^File]
- bytes: Cell#[^Word8]
+ files: Cell#[File]
+ bytes: Cell#[Word8]
f: File
b: Word8
-proc store#[T](target: ^Cell#[T]; value: T)
+proc store#[T](target: ^Cell#[T]; value: ^T)
target^.held := value
return
-proc relay#[T](target: ^Cell#[T]; value: T)
+proc relay#[T](target: ^Cell#[T]; value: ^T)
store(target, value)
return
diff --git a/testsuite/compilable/generic_pointee.elna b/testsuite/compilable/generic_pointee.elna
new file mode 100644
index 0000000..5ecaedf
--- /dev/null
+++ b/testsuite/compilable/generic_pointee.elna
@@ -0,0 +1,17 @@
+program()
+
+type
+ File = record
+ fd: Int
+ end
+
+proc allocate#[T](size: Word) -> ^T
+extern
+
+var
+ f: ^File
+
+begin
+ f := allocate#[File](#size(File));
+ assert(f = nil)
+end.
diff --git a/testsuite/fail_compilation/generic_arity.elna b/testsuite/fail_compilation/generic_arity.elna
index 645aded..3284a83 100644
--- a/testsuite/fail_compilation/generic_arity.elna
+++ b/testsuite/fail_compilation/generic_arity.elna
@@ -2,7 +2,7 @@ module
type
Stack#[T] = record
- items: T
+ items: ^T
end
var
diff --git a/testsuite/fail_compilation/generic_base_mismatch.elna b/testsuite/fail_compilation/generic_base_mismatch.elna
index e361052..dd3bec7 100644
--- a/testsuite/fail_compilation/generic_base_mismatch.elna
+++ b/testsuite/fail_compilation/generic_base_mismatch.elna
@@ -8,17 +8,17 @@ type
end
List#[T] = record
- head: T
+ head: ^T
end
Queue#[T] = record(List#[T])
- tail: T
+ tail: ^T
end
var
- jobs: Queue#[^File]
- wrong: ^List#[^Socket]
+ jobs: Queue#[File]
+ wrong: ^List#[Socket]
begin
- wrong := @jobs (* @Error Expected type '\^List#\[\^Socket\]', but got '\^Queue#\[\^File\]' *)
+ wrong := @jobs (* @Error Expected type '\^List#\[Socket\]', but got '\^Queue#\[File\]' *)
end.
diff --git a/testsuite/fail_compilation/generic_by_value.elna b/testsuite/fail_compilation/generic_by_value.elna
new file mode 100644
index 0000000..778feca
--- /dev/null
+++ b/testsuite/fail_compilation/generic_by_value.elna
@@ -0,0 +1,7 @@
+module
+
+proc foo#[T](x: T) (* @Error Opaque type 'T' cannot be used as a procedure parameter *)
+begin
+return
+
+end.
diff --git a/testsuite/fail_compilation/generic_field_by_value.elna b/testsuite/fail_compilation/generic_field_by_value.elna
new file mode 100644
index 0000000..66f9b46
--- /dev/null
+++ b/testsuite/fail_compilation/generic_field_by_value.elna
@@ -0,0 +1,8 @@
+module
+
+type
+ Cell#[T] = record
+ field: T (* @Error Opaque type 'T' cannot be used as a record field type *)
+ end
+
+end.
diff --git a/testsuite/fail_compilation/generic_parameter_arithmetic.elna b/testsuite/fail_compilation/generic_parameter_arithmetic.elna
index e05b1ee..9f6909d 100644
--- a/testsuite/fail_compilation/generic_parameter_arithmetic.elna
+++ b/testsuite/fail_compilation/generic_parameter_arithmetic.elna
@@ -1,9 +1,8 @@
module
-proc walk#[T](value: T; step: ^T)
+proc walk#[T](step: ^T)
begin
- step := step + 1;
- value := value + 1 (* @Error Type parameter 'T' cannot be used in pointer arithmetic *)
+ step := step + 1 (* @Error Type parameter 'T' cannot be used in pointer arithmetic *)
return
end.
diff --git a/testsuite/fail_compilation/generic_uninferrable.elna b/testsuite/fail_compilation/generic_uninferrable.elna
index b3556d6..7eca7a9 100644
--- a/testsuite/fail_compilation/generic_uninferrable.elna
+++ b/testsuite/fail_compilation/generic_uninferrable.elna
@@ -2,7 +2,7 @@ program()
var
got: ^Word8
-proc allocate#[R](size: Word) -> R
+proc allocate#[R](size: Word) -> ^R
extern
begin
diff --git a/testsuite/runnable/generic_base.elna b/testsuite/runnable/generic_base.elna
index 63737e0..161c59d 100644
--- a/testsuite/runnable/generic_base.elna
+++ b/testsuite/runnable/generic_base.elna
@@ -5,26 +5,26 @@ type
end
List#[T] = record
- head: T;
+ head: ^T;
count: Word
end
Queue#[T] = record(List#[T])
- tail: T
+ tail: ^T
end
var
- jobs: Queue#[^File]
- seen: ^List#[^File]
+ jobs: Queue#[File]
+ seen: ^List#[File]
f: File
-proc push#[T](target: ^List#[T]; value: T)
+proc push#[T](target: ^List#[T]; value: ^T)
begin
target^.head := value;
target^.count := target^.count + 1u
return
-proc enqueue#[T](target: ^Queue#[T]; value: T)
+proc enqueue#[T](target: ^Queue#[T]; value: ^T)
begin
push(target, value);
target^.tail := value
@@ -36,5 +36,5 @@ begin
assert(jobs.count = 1u);
assert(jobs.head = @f);
assert(jobs.tail = @f);
- assert(#size(Queue#[^File]) = #size(Pointer) * 3u)
+ assert(#size(Queue#[File]) = #size(Pointer) * 3u)
end.
diff --git a/testsuite/runnable/generic_constructor.elna b/testsuite/runnable/generic_constructor.elna
index d0a3f78..b21cd4a 100644
--- a/testsuite/runnable/generic_constructor.elna
+++ b/testsuite/runnable/generic_constructor.elna
@@ -5,16 +5,16 @@ type
end
Stack#[T] = record
- items: T;
+ items: ^T;
top: Word
end
var
- s: Stack#[^File]
+ s: Stack#[File]
f: File
begin
- s := Stack#[^File]{ top: 1u, items: @f };
+ s := Stack#[File]{ top: 1u, items: @f };
assert(s.top = 1u);
assert(s.items = @f)
end.
diff --git a/testsuite/runnable/generic_erasure.elna b/testsuite/runnable/generic_erasure.elna
index 20862fa..db4d8c9 100644
--- a/testsuite/runnable/generic_erasure.elna
+++ b/testsuite/runnable/generic_erasure.elna
@@ -5,16 +5,16 @@ type
end
Cell#[T] = record
- held: T
+ held: ^T
end
var
- files: Cell#[^File]
- bytes: Cell#[^Word8]
+ files: Cell#[File]
+ bytes: Cell#[Word8]
f: File
b: Word8
-proc store#[T](target: ^Cell#[T]; value: T)
+proc store#[T](target: ^Cell#[T]; value: ^T)
begin
target^.held := value
return
@@ -22,8 +22,8 @@ return
begin
f.fd := 7;
b := 3u8;
- store#[^File](@files, @f);
- store#[^Word8](@bytes, @b);
+ store#[File](@files, @f);
+ store#[Word8](@bytes, @b);
assert(files.held^.fd = 7);
assert(bytes.held^ = 3u8)
end.
diff --git a/testsuite/runnable/generic_record.elna b/testsuite/runnable/generic_record.elna
index 4164c3d..1fff97d 100644
--- a/testsuite/runnable/generic_record.elna
+++ b/testsuite/runnable/generic_record.elna
@@ -5,15 +5,15 @@ type
end
Stack#[T] = record
- items: T;
+ items: ^T;
top: Word
end
var
- s: Stack#[^File]
+ s: Stack#[File]
f: File
-proc push#[T](target: ^Stack#[T]; value: T)
+proc push#[T](target: ^Stack#[T]; value: ^T)
begin
target^.items := value;
target^.top := target^.top + 1u
@@ -21,7 +21,7 @@ return
begin
s.top := 0u;
- push#[^File](@s, @f);
+ push#[File](@s, @f);
assert(s.top = 1u);
assert(s.items = @f)
end.