Merge branch 'main' into fix-detect-libc

This commit is contained in:
Norbert Hajagos 2025-11-17 13:32:12 +01:00 committed by GitHub
commit dcb38b9034
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 122 additions and 172 deletions

View file

@ -1,12 +1,12 @@
Builtin := [].{
Str := [ProvidedByCompiler].{
Builtin :: [].{
Str :: [ProvidedByCompiler].{
is_empty : Str -> Bool
contains : Str, Str -> Bool
contains = |_str, _other| True
}
List := [ProvidedByCompiler].{
List :: [ProvidedByCompiler].{
len : List(_item) -> U64
is_empty : List(_item) -> Bool
concat : List(item), List(item) -> List(item)
@ -90,17 +90,25 @@ Builtin := [].{
#}
}
Dict := [EmptyDict].{}
Dict :: [EmptyDict].{}
Set(item) := [].{
Set(item) :: [].{
is_empty : Set(item) -> Bool
is_eq : Set(item), Set(item) -> Bool
is_eq = |_a, _b| Bool.False
}
Num := {}.{
U8 := [].{
Num :: {}.{
NumLiteral :: [Self(Bool)].{
is_negative : NumLiteral -> Bool
is_negative = |self| match self {
# TODO make this a nominal record once we have those
Self(is_negative) => is_negative
}
}
U8 :: [].{
is_zero : U8 -> Bool
is_eq : U8, U8 -> Bool
is_gt : U8, U8 -> Bool
@ -115,9 +123,10 @@ Builtin := [].{
rem_by : U8, U8 -> U8
from_int_digits : List(U8) -> Try(U8, [OutOfRange])
from_num_literal : NumLiteral -> Try(U8, [InvalidNumLiteral(Str)])
}
I8 := [].{
I8 :: [].{
is_zero : I8 -> Bool
is_negative : I8 -> Bool
is_positive : I8 -> Bool
@ -135,9 +144,10 @@ Builtin := [].{
rem_by : I8, I8 -> I8
from_int_digits : List(U8) -> Try(I8, [OutOfRange])
from_num_literal : NumLiteral -> Try(I8, [InvalidNumLiteral(Str)])
}
U16 := [].{
U16 :: [].{
is_zero : U16 -> Bool
is_eq : U16, U16 -> Bool
is_gt : U16, U16 -> Bool
@ -152,9 +162,10 @@ Builtin := [].{
rem_by : U16, U16 -> U16
from_int_digits : List(U8) -> Try(U16, [OutOfRange])
from_num_literal : NumLiteral -> Try(U16, [InvalidNumLiteral(Str)])
}
I16 := [].{
I16 :: [].{
is_zero : I16 -> Bool
is_negative : I16 -> Bool
is_positive : I16 -> Bool
@ -172,9 +183,10 @@ Builtin := [].{
rem_by : I16, I16 -> I16
from_int_digits : List(U8) -> Try(I16, [OutOfRange])
from_num_literal : NumLiteral -> Try(I16, [InvalidNumLiteral(Str)])
}
U32 := [].{
U32 :: [].{
is_zero : U32 -> Bool
is_eq : U32, U32 -> Bool
is_gt : U32, U32 -> Bool
@ -189,9 +201,10 @@ Builtin := [].{
rem_by : U32, U32 -> U32
from_int_digits : List(U8) -> Try(U32, [OutOfRange])
from_num_literal : NumLiteral -> Try(U32, [InvalidNumLiteral(Str)])
}
I32 := [].{
I32 :: [].{
is_zero : I32 -> Bool
is_negative : I32 -> Bool
is_positive : I32 -> Bool
@ -209,9 +222,10 @@ Builtin := [].{
rem_by : I32, I32 -> I32
from_int_digits : List(U8) -> Try(I32, [OutOfRange])
from_num_literal : NumLiteral -> Try(I32, [InvalidNumLiteral(Str)])
}
U64 := [].{
U64 :: [].{
is_zero : U64 -> Bool
is_eq : U64, U64 -> Bool
is_gt : U64, U64 -> Bool
@ -226,9 +240,10 @@ Builtin := [].{
rem_by : U64, U64 -> U64
from_int_digits : List(U8) -> Try(U64, [OutOfRange])
from_num_literal : NumLiteral -> Try(U64, [InvalidNumLiteral(Str)])
}
I64 := [].{
I64 :: [].{
is_zero : I64 -> Bool
is_negative : I64 -> Bool
is_positive : I64 -> Bool
@ -246,9 +261,10 @@ Builtin := [].{
rem_by : I64, I64 -> I64
from_int_digits : List(U8) -> Try(I64, [OutOfRange])
from_num_literal : NumLiteral -> Try(I64, [InvalidNumLiteral(Str)])
}
U128 := [].{
U128 :: [].{
is_zero : U128 -> Bool
is_eq : U128, U128 -> Bool
is_gt : U128, U128 -> Bool
@ -263,9 +279,10 @@ Builtin := [].{
rem_by : U128, U128 -> U128
from_int_digits : List(U8) -> Try(U128, [OutOfRange])
from_num_literal : NumLiteral -> Try(U128, [InvalidNumLiteral(Str)])
}
I128 := [].{
I128 :: [].{
is_zero : I128 -> Bool
is_negative : I128 -> Bool
is_positive : I128 -> Bool
@ -283,9 +300,10 @@ Builtin := [].{
rem_by : I128, I128 -> I128
from_int_digits : List(U8) -> Try(I128, [OutOfRange])
from_num_literal : NumLiteral -> Try(I128, [InvalidNumLiteral(Str)])
}
Dec := [].{
Dec :: [].{
is_zero : Dec -> Bool
is_negative : Dec -> Bool
is_positive : Dec -> Bool
@ -305,9 +323,10 @@ Builtin := [].{
from_int_digits : List(U8) -> Try(Dec, [OutOfRange])
from_dec_digits : (List(U8), List(U8)) -> Try(Dec, [OutOfRange])
from_num_literal : NumLiteral -> Try(Dec, [InvalidNumLiteral(Str)])
}
F32 := [].{
F32 :: [].{
is_zero : F32 -> Bool
is_negative : F32 -> Bool
is_positive : F32 -> Bool
@ -325,9 +344,10 @@ Builtin := [].{
from_int_digits : List(U8) -> Try(F32, [OutOfRange])
from_dec_digits : (List(U8), List(U8)) -> Try(F32, [OutOfRange])
from_num_literal : NumLiteral -> Try(F32, [InvalidNumLiteral(Str)])
}
F64 := [].{
F64 :: [].{
is_zero : F64 -> Bool
is_negative : F64 -> Bool
is_positive : F64 -> Bool
@ -345,6 +365,7 @@ Builtin := [].{
from_int_digits : List(U8) -> Try(F64, [OutOfRange])
from_dec_digits : (List(U8), List(U8)) -> Try(F64, [OutOfRange])
from_num_literal : NumLiteral -> Try(F64, [InvalidNumLiteral(Str)])
}
}
}

View file

@ -562,7 +562,11 @@ fn processAssociatedBlock(
try current_scope.introduceTypeAlias(self.env.gpa, user_qualified_ident_idx, qualified_type_decl_idx);
}
// Introduce associated items of nested types
// Introduce associated items of nested types into this scope
// Note: Nested types with associated blocks were already fully processed
// during processAssociatedItemsFirstPass (Phase 2b), so these items are
// NOT placeholders - they're fully processed definitions.
// We're just aliasing them into this scope for convenience.
if (nested_type_decl.associated) |nested_assoc| {
for (self.parse_ir.store.statementSlice(nested_assoc.statements)) |nested_assoc_stmt_idx| {
const nested_assoc_stmt = self.parse_ir.store.getStatement(nested_assoc_stmt_idx);
@ -572,7 +576,7 @@ fn processAssociatedBlock(
if (nested_pattern == .ident) {
const nested_pattern_ident_tok = nested_pattern.ident.ident_tok;
if (self.parse_ir.tokens.resolveIdentifier(nested_pattern_ident_tok)) |nested_decl_ident| {
// Build fully qualified name (e.g., "Test.MyBool.my_not")
// Build fully qualified name (e.g., "Builtin.Num.NumLiteral.is_negative")
const qualified_text = self.env.getIdent(qualified_ident_idx);
const nested_decl_text = self.env.getIdent(nested_decl_ident);
const full_qualified_ident_idx = try self.env.insertQualifiedIdent(qualified_text, nested_decl_text);
@ -582,21 +586,15 @@ fn processAssociatedBlock(
.found => |pattern_idx| {
const scope = &self.scopes.items[self.scopes.items.len - 1];
// Check if this is a placeholder
const is_placeholder = self.isPlaceholder(full_qualified_ident_idx);
// Just add aliases to scope - don't track as placeholders
// because these were already fully processed
// Add unqualified name (e.g., "my_not")
// Add unqualified name (e.g., "is_negative")
try scope.idents.put(self.env.gpa, nested_decl_ident, pattern_idx);
if (is_placeholder) {
try self.placeholder_idents.put(self.env.gpa, nested_decl_ident, {});
}
// Add type-qualified name (e.g., "MyBool.my_not")
// Add type-qualified name (e.g., "NumLiteral.is_negative")
const type_qualified_ident_idx = try self.env.insertQualifiedIdent(nested_type_text, nested_decl_text);
try scope.idents.put(self.env.gpa, type_qualified_ident_idx, pattern_idx);
if (is_placeholder) {
try self.placeholder_idents.put(self.env.gpa, type_qualified_ident_idx, {});
}
},
.not_found => {},
}
@ -862,18 +860,25 @@ fn processAssociatedItemsSecondPass(
const pattern_idx = def_cir.pattern;
const current_scope = &self.scopes.items[self.scopes.items.len - 1];
// Update unqualified name (e.g., "my_not")
try self.updatePlaceholder(current_scope, decl_ident, pattern_idx);
// Check if this is still a placeholder before updating.
// For nested types with associated blocks (e.g., NumLiteral inside Num),
// the item may have already been fully processed during the recursive
// processAssociatedBlock call in Phase 2b of processAssociatedItemsFirstPass.
// In that case, the placeholder was already consumed and we should skip it.
if (self.isPlaceholder(decl_ident)) {
// Update unqualified name (e.g., "my_not")
try self.updatePlaceholder(current_scope, decl_ident, pattern_idx);
// Update type-qualified name (e.g., "MyBool.my_not")
const type_qualified_idx = try self.env.insertQualifiedIdent(self.env.getIdent(parent_type_name), decl_text);
if (type_qualified_idx.idx != decl_ident.idx) {
try self.updatePlaceholder(current_scope, type_qualified_idx, pattern_idx);
}
// Update type-qualified name (e.g., "MyBool.my_not")
const type_qualified_idx = try self.env.insertQualifiedIdent(self.env.getIdent(parent_type_name), decl_text);
if (type_qualified_idx.idx != decl_ident.idx) {
try self.updatePlaceholder(current_scope, type_qualified_idx, pattern_idx);
}
// Update fully qualified name (e.g., "Test.MyBool.my_not")
if (qualified_idx.idx != type_qualified_idx.idx and qualified_idx.idx != decl_ident.idx) {
try self.updatePlaceholder(current_scope, qualified_idx, pattern_idx);
// Update fully qualified name (e.g., "Test.MyBool.my_not")
if (qualified_idx.idx != type_qualified_idx.idx and qualified_idx.idx != decl_ident.idx) {
try self.updatePlaceholder(current_scope, qualified_idx, pattern_idx);
}
}
break :blk true; // Found and processed matching decl

View file

@ -323,6 +323,11 @@ pub const Layout = packed struct {
return Layout{ .data = .{ .scalar = .{ .data = .{ .frac = precision }, .tag = .frac } }, .tag = .scalar };
}
/// Default number layout (Dec) for unresolved polymorphic number types
pub fn default_num() Layout {
return Layout.frac(.dec);
}
/// bool layout
pub fn boolType() Layout {
return Layout{ .data = .{ .scalar = .{ .data = .{ .bool = {} }, .tag = .bool } }, .tag = .scalar };

View file

@ -912,23 +912,23 @@ pub const Store = struct {
.frac_precision => |precision| break :flat_type Layout.frac(precision),
// For polymorphic types, use default precision
.num_unbound => |_| {
// TODO: Should we consider requirements here?
break :flat_type Layout.int(types.Num.Int.Precision.default);
// Default unbound number types to Dec
break :flat_type Layout.default_num();
},
.int_unbound => {
// TODO: Should we consider requirements here?
break :flat_type Layout.int(types.Num.Int.Precision.default);
// Default unbound int types to Dec
break :flat_type Layout.default_num();
},
.frac_unbound => {
// TODO: Should we consider requirements here?
break :flat_type Layout.frac(types.Num.Frac.Precision.default);
// Default unbound frac types to Dec
break :flat_type Layout.default_num();
},
.num_poly => |var_| {
const next_type = self.types_store.resolveVar(var_).desc.content;
if (next_type == .structure and next_type.structure == .num) {
num = next_type.structure.num;
} else if (next_type == .flex) {
break :flat_type Layout.int(types.Num.Int.Precision.default);
break :flat_type Layout.default_num();
} else {
return LayoutError.InvalidRecordExtension;
}
@ -938,7 +938,7 @@ pub const Store = struct {
if (next_type == .structure and next_type.structure == .num) {
num = next_type.structure.num;
} else if (next_type == .flex) {
break :flat_type Layout.int(types.Num.Int.Precision.default);
break :flat_type Layout.default_num();
} else {
return LayoutError.InvalidRecordExtension;
}
@ -948,7 +948,7 @@ pub const Store = struct {
if (next_type == .structure and next_type.structure == .num) {
num = next_type.structure.num;
} else if (next_type == .flex) {
break :flat_type Layout.frac(types.Num.Frac.Precision.default);
break :flat_type Layout.default_num();
} else {
return LayoutError.InvalidRecordExtension;
}
@ -1315,8 +1315,8 @@ pub const Store = struct {
// Flex vars appear in REPL/eval contexts where type constraints haven't been fully solved.
// This is a known issue that needs proper constraint solving before layout computation.
// For now, default to I64 for numeric flex vars.
break :blk Layout.int(.i64);
// For now, default to Dec for unresolved polymorphic types.
break :blk Layout.default_num();
},
.rigid => blk: {
// First, check if this rigid var is mapped in the TypeScope

View file

@ -83,23 +83,23 @@ test "addTypeVar - default layouts for polymorphic types" {
lt.type_scope = TypeScope.init(lt.gpa);
defer lt.deinit();
// Flex number var (Num a) defaults to i128
// Flex number var (Num a) defaults to Dec
const num_var = try lt.type_store.fresh();
const flex_num_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .num_poly = num_var } } });
const num_layout_idx = try lt.layout_store.addTypeVar(flex_num_var, &lt.type_scope);
const num_layout = lt.layout_store.getLayout(num_layout_idx);
try testing.expect(num_layout.tag == .scalar);
try testing.expect(num_layout.data.scalar.data.int == .i128);
try testing.expect(num_layout.data.scalar.data.frac == .dec);
// Flex int var (Int a) defaults to i128
// Flex int var (Int a) defaults to Dec
const int_var = try lt.type_store.fresh();
const flex_int_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .int_poly = int_var } } });
const int_layout_idx = try lt.layout_store.addTypeVar(flex_int_var, &lt.type_scope);
const int_layout = lt.layout_store.getLayout(int_layout_idx);
try testing.expect(int_layout.tag == .scalar);
try testing.expect(int_layout.data.scalar.data.int == .i128);
try testing.expect(int_layout.data.scalar.data.frac == .dec);
// Flex frac var (Frac a) defaults to dec
// Flex frac var (Frac a) defaults to Dec
const frac_var = try lt.type_store.fresh();
const flex_frac_var = try lt.type_store.freshFromContent(.{ .structure = .{ .num = .{ .frac_poly = frac_var } } });
const frac_layout_idx = try lt.layout_store.addTypeVar(flex_frac_var, &lt.type_scope);

View file

@ -1207,11 +1207,11 @@ fn parseStmtByType(self: *Parser, statementType: StatementType) Error!AST.Statem
const start = self.pos;
if (statementType == .top_level or statementType == .in_associated_block) {
const header = try self.parseTypeHeader();
if (self.peek() != .OpColon and self.peek() != .OpColonEqual) {
if (self.peek() != .OpColon and self.peek() != .OpColonEqual and self.peek() != .OpDoubleColon) {
// Point to the unexpected token (e.g., "U8" in "List U8")
return try self.pushMalformed(AST.Statement.Idx, .expected_colon_after_type_annotation, self.pos);
}
const kind: AST.TypeDeclKind = if (self.peek() == .OpColonEqual) .nominal else .alias;
const kind: AST.TypeDeclKind = if (self.peek() == .OpColonEqual or self.peek() == .OpDoubleColon) .nominal else .alias;
self.advance();
const anno = try self.parseTypeAnno(.not_looking_for_args);
const where_clause = try self.parseWhereConstraint();

View file

@ -117,6 +117,7 @@ pub const Token = struct {
OpLessThan,
OpEquals,
OpColonEqual,
OpDoubleColon,
NoSpaceOpQuestion,
Comma,
@ -257,6 +258,7 @@ pub const Token = struct {
.OpLessThan,
.OpEquals,
.OpColonEqual,
.OpDoubleColon,
.NoSpaceOpQuestion,
.Comma,
.Dot,
@ -1389,6 +1391,9 @@ pub const Tokenizer = struct {
if (self.cursor.peekAt(1) == '=') {
self.cursor.pos += 2;
try self.pushTokenNormalHere(gpa, .OpColonEqual, start);
} else if (self.cursor.peekAt(1) == ':') {
self.cursor.pos += 2;
try self.pushTokenNormalHere(gpa, .OpDoubleColon, start);
} else {
self.cursor.pos += 1;
try self.pushTokenNormalHere(gpa, .OpColon, start);
@ -2140,6 +2145,11 @@ fn rebuildBufferForTesting(buf: []const u8, tokens: *TokenizedBuffer, alloc: std
try buf2.append(':');
try buf2.append('=');
},
.OpDoubleColon => {
std.debug.assert(length == 2);
try buf2.append(':');
try buf2.append(':');
},
.Comma => {
std.debug.assert(length == 1);

View file

@ -9,20 +9,13 @@ modu:;::::::::::::::le[%
~~~
# EXPECTED
UNEXPECTED TOKEN IN TYPE ANNOTATION - fuzz_crash_002.md:1:6:1:7
PARSE ERROR - fuzz_crash_002.md:1:7:1:8
PARSE ERROR - fuzz_crash_002.md:1:8:1:9
PARSE ERROR - fuzz_crash_002.md:1:9:1:10
PARSE ERROR - fuzz_crash_002.md:1:10:1:11
PARSE ERROR - fuzz_crash_002.md:1:11:1:12
PARSE ERROR - fuzz_crash_002.md:1:12:1:13
PARSE ERROR - fuzz_crash_002.md:1:13:1:14
PARSE ERROR - fuzz_crash_002.md:1:14:1:15
PARSE ERROR - fuzz_crash_002.md:1:15:1:16
PARSE ERROR - fuzz_crash_002.md:1:16:1:17
PARSE ERROR - fuzz_crash_002.md:1:17:1:18
PARSE ERROR - fuzz_crash_002.md:1:18:1:19
PARSE ERROR - fuzz_crash_002.md:1:19:1:20
PARSE ERROR - fuzz_crash_002.md:1:20:1:21
PARSE ERROR - fuzz_crash_002.md:1:7:1:9
PARSE ERROR - fuzz_crash_002.md:1:9:1:11
PARSE ERROR - fuzz_crash_002.md:1:11:1:13
PARSE ERROR - fuzz_crash_002.md:1:13:1:15
PARSE ERROR - fuzz_crash_002.md:1:15:1:17
PARSE ERROR - fuzz_crash_002.md:1:17:1:19
PARSE ERROR - fuzz_crash_002.md:1:19:1:21
PARSE ERROR - fuzz_crash_002.md:1:21:1:23
PARSE ERROR - fuzz_crash_002.md:1:23:1:24
PARSE ERROR - fuzz_crash_002.md:1:24:1:25
@ -44,154 +37,77 @@ modu:;::::::::::::::le[%
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:7:1:8:**
**fuzz_crash_002.md:1:7:1:9:**
```roc
modu:;::::::::::::::le[%
```
^
^^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:8:1:9:**
**fuzz_crash_002.md:1:9:1:11:**
```roc
modu:;::::::::::::::le[%
```
^
^^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:9:1:10:**
**fuzz_crash_002.md:1:11:1:13:**
```roc
modu:;::::::::::::::le[%
```
^
^^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:10:1:11:**
**fuzz_crash_002.md:1:13:1:15:**
```roc
modu:;::::::::::::::le[%
```
^
^^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:11:1:12:**
**fuzz_crash_002.md:1:15:1:17:**
```roc
modu:;::::::::::::::le[%
```
^
^^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:12:1:13:**
**fuzz_crash_002.md:1:17:1:19:**
```roc
modu:;::::::::::::::le[%
```
^
^^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:13:1:14:**
**fuzz_crash_002.md:1:19:1:21:**
```roc
modu:;::::::::::::::le[%
```
^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:14:1:15:**
```roc
modu:;::::::::::::::le[%
```
^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:15:1:16:**
```roc
modu:;::::::::::::::le[%
```
^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:16:1:17:**
```roc
modu:;::::::::::::::le[%
```
^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:17:1:18:**
```roc
modu:;::::::::::::::le[%
```
^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:18:1:19:**
```roc
modu:;::::::::::::::le[%
```
^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:19:1:20:**
```roc
modu:;::::::::::::::le[%
```
^
**PARSE ERROR**
A parsing error occurred: `statement_unexpected_token`
This is an unexpected parsing error. Please check your syntax.
**fuzz_crash_002.md:1:20:1:21:**
```roc
modu:;::::::::::::::le[%
```
^
^^
**PARSE ERROR**
@ -253,7 +169,7 @@ modu:;::::::::::::::le[%
# TOKENS
~~~zig
LowerIdent,OpColon,MalformedUnknownToken,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,OpColon,LowerIdent,OpenSquare,OpPercent,
LowerIdent,OpColon,MalformedUnknownToken,OpDoubleColon,OpDoubleColon,OpDoubleColon,OpDoubleColon,OpDoubleColon,OpDoubleColon,OpDoubleColon,LowerIdent,OpenSquare,OpPercent,
EndOfFile,
~~~
# PARSE
@ -272,13 +188,6 @@ EndOfFile,
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))
(s-malformed (tag "statement_unexpected_token"))))
~~~
# FORMATTED