Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
469 changes: 238 additions & 231 deletions compiler/bytecode.casa

Large diffs are not rendered by default.

14 changes: 2 additions & 12 deletions compiler/lexer.casa
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,7 @@ impl Lexer {
loc "Expected two hex digits after \\x" ErrorKind::Syntax self.add_error
"" Option::Some return
fi
if high_opt Option::Some(high) is then
high hex_digit_value = high_value
else
empty_location "Expected high hex digit" ErrorKind::Syntax raise_error
1 exit
fi
high_opt.unwrap hex_digit_value = high_value
if 0 high_value < then
3 self Lexer::cursor Cursor::pos 3 - self.loc = loc
loc "Invalid hex digit in \\x escape" ErrorKind::Syntax self.add_error
Expand All @@ -119,12 +114,7 @@ impl Lexer {
loc "Expected two hex digits after \\x" ErrorKind::Syntax self.add_error
"" Option::Some return
fi
if low_opt Option::Some(low) is then
low hex_digit_value = low_value
else
empty_location "Expected low hex digit" ErrorKind::Syntax raise_error
1 exit
fi
low_opt.unwrap hex_digit_value = low_value
if 0 low_value < then
4 self Lexer::cursor Cursor::pos 4 - self.loc = loc
loc "Invalid hex digit in \\x escape" ErrorKind::Syntax self.add_error
Expand Down
24 changes: 21 additions & 3 deletions compiler/pattern.casa
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ fn unify_arm_stacks tc:TypeChecker match_ctx:MatchContext op:Op {
# by a struct destructure arm.

fn assign_struct_binding_type
tc:TypeChecker
matched_struct:CasaStruct
field_name:str
bound_var:str
Expand All @@ -152,7 +153,7 @@ fn assign_struct_binding_type
{
for member in matched_struct CasaStruct::members.iter do
if field_name member Member::name == then
store function_opt member Member::typ bound_var set_binding_type
store function_opt member Member::typ bound_var tc set_binding_type
fi
done
}
Expand All @@ -171,7 +172,7 @@ fn register_struct_pattern_bindings
struct_pattern StructPattern::bindings.keys = binding_keys
for field_name in binding_keys.iter do
if field_name struct_pattern StructPattern::bindings.get Option::Some(bound_var) is then
tc.store function_opt bound_var field_name matched_struct assign_struct_binding_type
tc.store function_opt bound_var field_name matched_struct tc assign_struct_binding_type
else
empty_location "Expected option value while unwrapping field_name struct_pattern StructPattern::bindings.get" ErrorKind::Syntax raise_error
1 exit
Expand Down Expand Up @@ -233,7 +234,7 @@ fn apply_enum_bindings
if binding_type.format type_bindings.get Option::Some(resolved) is then
resolved = binding_type
fi
tc.store function_opt binding_type binding_var set_binding_type
tc.store function_opt binding_type binding_var tc set_binding_type
1 += bind_index
done
}
Expand Down Expand Up @@ -275,6 +276,10 @@ fn typecheck_match_op tc:TypeChecker function_opt:Option[Function] op:Op {
op pattern_covered_key = covered_key
match_subject_type parse_type_str.match_base = arm_base

# A prior arm has already opened (and left open) its scope frame iff the
# match has seen a condition. Capture this before the block below sets it.
match_ctx MatchContext::condition_present = arm_has_predecessor

if op pattern_value_of PatternValue::EnumVariant(variant) is then
if op pattern_is_wildcard ! then
arm_base variant op tc diagnose_bare_enum_pattern
Expand All @@ -291,11 +296,24 @@ fn typecheck_match_op tc:TypeChecker function_opt:Option[Function] op:Op {
tc.stack match_ctx MatchContext::after.restore
fi

# Each arm body gets its own scope frame: pattern bindings and any
# block-local assignments live here, invisible to other arms and after
# `end`. Close the previous arm's frame before opening this one.
if arm_has_predecessor then tc.pop_block_scope fi
tc.push_block_scope

# Record pattern bindings in the arm scope; implicit bindings cannot
# shadow an accessible outer variable (same rule as is-bindings).
for binding_var in op pattern_bindings.iter do
true op binding_var tc.record_var_scope
done

match_subject_type op function_opt tc register_pattern_bindings

if op pattern_is_guarded then
op pattern_guard_ops = guard_ops
tc.store TypeChecker::new = guard_checker
guard_checker tc.copy_scope_state_to
function_opt guard_ops guard_checker.run_type_check_ops
guard_checker.stack.types = guard_stack
false = guard_ok
Expand Down
90 changes: 41 additions & 49 deletions compiler/syntax.casa
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ fn parse_type_ast cursor:TokenCursor -> Type {
fi
peek_opt.unwrap = peek

"" = base
if "fn" peek Token::value == then
cursor.pop drop
"fn" = base
Expand All @@ -252,11 +253,7 @@ fn parse_type_ast cursor:TokenCursor -> Type {
while cursor.is_finished ! do
cursor.peek = inner_opt
if inner_opt.is_none then break fi
if inner_opt Option::Some(inner) is then
inner Token::value = ival
else
break
fi
inner_opt.unwrap Token::value = ival
if "]" ival == then
cursor.pop drop
break
Expand Down Expand Up @@ -738,11 +735,7 @@ fn parse_bound_type_args cursor:TokenCursor trait_token:Token -> List[str] {
trait_token Token::location "Unclosed trait bound type argument list" ErrorKind::Syntax raise_error
bound_args return
fi
if arg_tok_opt Option::Some(arg_tok) is then
arg_tok Token::value = arg_val
else
bound_args return
fi
arg_tok_opt.unwrap Token::value = arg_val
if "[" arg_val == then
1 += pba_depth
arg_val pba_current.append
Expand Down Expand Up @@ -1960,6 +1953,7 @@ fn parse_impl_block parser:Parser cursor:TokenCursor {

# Get base type name (without type params)
impl_type "[" str::find = bracket
"" = base_type
if 0 bracket > then
impl_type 0 bracket str::substring = base_type
else
Expand Down Expand Up @@ -2083,11 +2077,7 @@ fn parse_pattern_terminator parser:Parser cursor:TokenCursor function_name:str -
while cursor.is_finished ! do
cursor.peek = next_opt
if next_opt.is_none then break fi
if next_opt Option::Some(next) is then
next Token::value = next_value
else
break
fi
next_opt.unwrap Token::value = next_value
if "=>" next_value == 0 match_depth == && then break fi
cursor.pop = guard_token_opt
if guard_token_opt.is_none then break fi
Expand Down Expand Up @@ -3160,23 +3150,24 @@ fn parse_and_resolve tokens:List[Token] search_paths:List[str] -> ParseResolveRe

fn gather_captures store:SymbolStore lambda_function:Function function:Function {
for op in lambda_function Function::ops.iter do
if op.value OpValue::Identifier(name) is ! then continue fi
false = captured

# Check enclosing function variables
for variable in function Function::variables.iter do
if name variable Variable::name == then
variable lambda_function Function::captures.push
true = captured
break
fi
done
if op.value OpValue::Identifier(name) is then
false = captured

# Check enclosing function variables
for variable in function Function::variables.iter do
if name variable Variable::name == then
variable lambda_function Function::captures.push
true = captured
break
fi
done

if captured ! then
# Check global variables
name store.variables.get = global_var_opt
if global_var_opt Option::Some(global_var) is then
global_var lambda_function Function::captures.push
if captured ! then
# Check global variables
name store.variables.get = global_var_opt
if global_var_opt Option::Some(global_var) is then
global_var lambda_function Function::captures.push
fi
fi
fi
done
Expand Down Expand Up @@ -3422,24 +3413,25 @@ fn register_struct_pattern_binding store:SymbolStore function:Function binding_n
}

fn resolve_match_op store:SymbolStore function:Function op:Op errors:List[CasaError] {
if op.value OpValue::MatchArm(arm) is ! then return fi
arm.pattern_value match
PatternValue::Struct(struct_pattern) => {
struct_pattern.bindings.keys = pattern_keys
for pattern_key in pattern_keys.iter do
pattern_key struct_pattern.bindings.get.unwrap = binding_name
binding_name function store register_struct_pattern_binding
done
}
PatternValue::EnumVariant(variant) => {
errors function op variant store resolve_enum_variant
}
PatternValue::Literal => { }
end
arm.guard_ops = guard_ops
if guard_ops.length 0 != then
function guard_ops store resolve_identifiers = resolved_guard
resolved_guard arm MatchArm::set_guard_ops
if op.value OpValue::MatchArm(arm) is then
arm.pattern_value match
PatternValue::Struct(struct_pattern) => {
struct_pattern.bindings.keys = pattern_keys
for pattern_key in pattern_keys.iter do
pattern_key struct_pattern.bindings.get.unwrap = binding_name
binding_name function store register_struct_pattern_binding
done
}
PatternValue::EnumVariant(variant) => {
errors function op variant store resolve_enum_variant
}
PatternValue::Literal => { }
end
arm.guard_ops = guard_ops
if guard_ops.length 0 != then
function guard_ops store resolve_identifiers = resolved_guard
resolved_guard arm MatchArm::set_guard_ops
fi
fi
}
# Try resolving `&name` and `&K::method` function references. Returns true
Expand Down
Loading