[fine] Starting on pattern matching, make patterns explicit

This commit is contained in:
John Doty 2024-02-04 07:47:16 -08:00
parent f00b9e22e7
commit deed9d9a45
4 changed files with 178 additions and 50 deletions

View file

@ -2,7 +2,7 @@ use std::collections::HashMap;
use std::rc::Rc;
use crate::{
parser::{SyntaxTree, Tree, TreeKind, TreeRef},
parser::{Child, SyntaxTree, Tree, TreeKind, TreeRef},
semantics::{Declaration, Location, Semantics, Type},
tokens::TokenKind,
};
@ -298,7 +298,7 @@ fn compile_expression(c: &mut Compiler, t: TreeRef) {
TreeKind::FieldValue => compile_field_value(c, t, tree),
TreeKind::GroupingExpression => compile_grouping(c, tree),
TreeKind::Identifier => compile_identifier_expression(c, t, tree),
TreeKind::IsExpression => compile_is_expression(c, t, tree),
TreeKind::IsExpression => compile_is_expression(c, tree),
TreeKind::LiteralExpression => compile_literal(c, t, tree),
TreeKind::MemberAccess => compile_member_access(c, tree),
TreeKind::NewObjectExpression => compile_new_object_expression(c, t, tree),
@ -620,50 +620,56 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
OK
}
fn compile_is_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> Option<()> {
fn compile_is_expression(c: &mut Compiler, tree: &Tree) -> Option<()> {
compile_expression(c, tree.nth_tree(0)?);
compile_pattern(c, tree.nth_tree(2)?)
}
fn compile_pattern(c: &mut Compiler, t: TreeRef) -> Option<()> {
let tree = &c.syntax[t];
// If you have a binding, dup and store now, it is in scope.
let type_expr =
if let Some(binding) = tree.child_tree_of_kind(c.syntax, TreeKind::VariableBinding) {
if let Some(variable) = binding.nth_token(0) {
let environment = c.semantics.environment_of(t);
let declaration = environment.bind(variable)?;
if let Some(binding) = tree.child_tree_of_kind(c.syntax, TreeKind::VariableBinding) {
if let Some(variable) = binding.nth_token(0) {
let environment = c.semantics.environment_of(t);
let declaration = environment.bind(variable)?;
let Declaration::Variable {
location: Location::Local,
index,
..
} = declaration
else {
ice!(c, t, "is cannot make a non-local, non-variable declaration")
};
let Declaration::Variable {
location: Location::Local,
index,
..
} = declaration
else {
ice!(c, t, "is cannot make a non-local, non-variable declaration")
};
c.push(Instruction::Dup);
c.push(Instruction::StoreLocal(*index));
}
binding.child_tree_of_kind(c.syntax, TreeKind::TypeExpression)?
} else {
tree.child_tree_of_kind(c.syntax, TreeKind::TypeExpression)?
};
compile_type_expr_eq(c, type_expr.nth_tree(0)?);
if let Some(tok) = tree.nth_token(3) {
if tok.kind == TokenKind::And {
let jump_true_index = c.push(Instruction::JumpTrue(0));
c.push(Instruction::PushFalse);
let jump_end_index = c.push(Instruction::Jump(0));
c.patch(jump_true_index, |i| Instruction::JumpTrue(i));
compile_expression(c, tree.nth_tree(4)?);
c.patch(jump_end_index, |i| Instruction::Jump(i));
c.push(Instruction::Dup);
c.push(Instruction::StoreLocal(*index));
}
}
let type_expr = tree.child_tree_of_kind(c.syntax, TreeKind::TypeExpression)?;
compile_type_expr_eq(c, type_expr.nth_tree(0)?);
let and_index = tree.children.iter().position(|c| match c {
Child::Token(t) => t.kind == TokenKind::And,
_ => false,
});
if let Some(and_index) = and_index {
// This is the tail end of an "AND" expression.
let jump_true_index = c.push(Instruction::JumpTrue(0));
c.push(Instruction::PushFalse);
let jump_end_index = c.push(Instruction::Jump(0));
c.patch(jump_true_index, |i| Instruction::JumpTrue(i));
compile_expression(c, tree.nth_tree(and_index + 1)?);
c.patch(jump_end_index, |i| Instruction::Jump(i));
};
OK
}