Run rustfmt on ast module

This commit is contained in:
Greg Shuflin 2021-10-28 02:00:37 -07:00
parent 765a0bec58
commit 5d04a020dc
3 changed files with 210 additions and 282 deletions

View File

@ -1,18 +1,22 @@
#![allow(clippy::upper_case_acronyms)] #![allow(clippy::upper_case_acronyms)]
#![allow(clippy::enum_variant_names)] #![allow(clippy::enum_variant_names)]
use std::rc::Rc; use std::{
use std::convert::{AsRef, From}; convert::{AsRef, From},
rc::Rc,
};
mod visitor;
mod operators; mod operators;
mod visitor;
pub use operators::{PrefixOp, BinOp}; pub use operators::{BinOp, PrefixOp};
pub use visitor::*; pub use visitor::*;
use crate::derivative::Derivative; use crate::{
use crate::tokenizing::Location; derivative::Derivative,
use crate::identifier::{Id, define_id_kind}; identifier::{define_id_kind, Id},
tokenizing::Location,
};
define_id_kind!(ASTItem); define_id_kind!(ASTItem);
@ -29,32 +33,32 @@ pub type ItemId = Id<ASTItem>;
#[derive(Derivative, Debug)] #[derive(Derivative, Debug)]
#[derivative(PartialEq)] #[derivative(PartialEq)]
pub struct AST { pub struct AST {
#[derivative(PartialEq="ignore")] #[derivative(PartialEq = "ignore")]
pub id: ItemId, pub id: ItemId,
pub statements: Block, pub statements: Block,
} }
#[derive(Derivative, Debug, Clone)] #[derive(Derivative, Debug, Clone)]
#[derivative(PartialEq)] #[derivative(PartialEq)]
pub struct Statement { pub struct Statement {
#[derivative(PartialEq="ignore")] #[derivative(PartialEq = "ignore")]
pub id: ItemId, pub id: ItemId,
#[derivative(PartialEq="ignore")] #[derivative(PartialEq = "ignore")]
pub location: Location, pub location: Location,
pub kind: StatementKind, pub kind: StatementKind,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum StatementKind { pub enum StatementKind {
Expression(Expression), Expression(Expression),
Declaration(Declaration), Declaration(Declaration),
Import(ImportSpecifier), Import(ImportSpecifier),
Module(ModuleSpecifier), Module(ModuleSpecifier),
} }
#[derive(Debug, Clone, PartialEq, Default)] #[derive(Debug, Clone, PartialEq, Default)]
pub struct Block { pub struct Block {
pub statements: Vec<Statement> pub statements: Vec<Statement>,
} }
impl From<Vec<Statement>> for Block { impl From<Vec<Statement>> for Block {
@ -80,59 +84,37 @@ pub type ParamName = Rc<String>;
#[derive(Debug, Derivative, Clone)] #[derive(Debug, Derivative, Clone)]
#[derivative(PartialEq)] #[derivative(PartialEq)]
pub struct QualifiedName { pub struct QualifiedName {
#[derivative(PartialEq="ignore")] #[derivative(PartialEq = "ignore")]
pub id: ItemId, pub id: ItemId,
pub components: Vec<Rc<String>>, pub components: Vec<Rc<String>>,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct FormalParam { pub struct FormalParam {
pub name: ParamName, pub name: ParamName,
pub default: Option<Expression>, pub default: Option<Expression>,
pub anno: Option<TypeIdentifier> pub anno: Option<TypeIdentifier>,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Declaration { pub enum Declaration {
FuncSig(Signature), FuncSig(Signature),
FuncDecl(Signature, Block), FuncDecl(Signature, Block),
TypeDecl { TypeDecl { name: TypeSingletonName, body: TypeBody, mutable: bool },
name: TypeSingletonName, //TODO this needs to be more sophisticated
body: TypeBody, TypeAlias { alias: Rc<String>, original: Rc<String> },
mutable: bool Binding { name: Rc<String>, constant: bool, type_anno: Option<TypeIdentifier>, expr: Expression },
}, Impl { type_name: TypeIdentifier, interface_name: Option<TypeSingletonName>, block: Vec<Declaration> },
//TODO this needs to be more sophisticated Interface { name: Rc<String>, signatures: Vec<Signature> },
TypeAlias { Annotation { name: Rc<String>, arguments: Vec<Expression> },
alias: Rc<String>,
original: Rc<String>,
},
Binding {
name: Rc<String>,
constant: bool,
type_anno: Option<TypeIdentifier>,
expr: Expression,
},
Impl {
type_name: TypeIdentifier,
interface_name: Option<TypeSingletonName>,
block: Vec<Declaration>,
},
Interface {
name: Rc<String>,
signatures: Vec<Signature>
},
Annotation {
name: Rc<String>,
arguments: Vec<Expression>
}
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Signature { pub struct Signature {
pub name: Rc<String>, pub name: Rc<String>,
pub operator: bool, pub operator: bool,
pub params: Vec<FormalParam>, pub params: Vec<FormalParam>,
pub type_anno: Option<TypeIdentifier>, pub type_anno: Option<TypeIdentifier>,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -141,184 +123,147 @@ pub struct TypeBody(pub Vec<Variant>);
#[derive(Debug, Derivative, Clone)] #[derive(Debug, Derivative, Clone)]
#[derivative(PartialEq)] #[derivative(PartialEq)]
pub struct Variant { pub struct Variant {
#[derivative(PartialEq="ignore")] #[derivative(PartialEq = "ignore")]
pub id: ItemId, pub id: ItemId,
pub name: Rc<String>, pub name: Rc<String>,
pub kind: VariantKind, pub kind: VariantKind,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum VariantKind { pub enum VariantKind {
UnitStruct, UnitStruct,
TupleStruct(Vec<TypeIdentifier>), TupleStruct(Vec<TypeIdentifier>),
Record(Vec<(Rc<String>, TypeIdentifier)>), Record(Vec<(Rc<String>, TypeIdentifier)>),
} }
#[derive(Debug, Derivative, Clone)] #[derive(Debug, Derivative, Clone)]
#[derivative(PartialEq)] #[derivative(PartialEq)]
pub struct Expression { pub struct Expression {
#[derivative(PartialEq="ignore")] #[derivative(PartialEq = "ignore")]
pub id: ItemId, pub id: ItemId,
pub kind: ExpressionKind, pub kind: ExpressionKind,
pub type_anno: Option<TypeIdentifier> pub type_anno: Option<TypeIdentifier>,
} }
impl Expression { impl Expression {
pub fn new(id: ItemId, kind: ExpressionKind) -> Expression { pub fn new(id: ItemId, kind: ExpressionKind) -> Expression {
Expression { id, kind, type_anno: None } Expression { id, kind, type_anno: None }
} }
#[cfg(test)] #[cfg(test)]
pub fn with_anno(id: ItemId, kind: ExpressionKind, type_anno: TypeIdentifier) -> Expression { pub fn with_anno(id: ItemId, kind: ExpressionKind, type_anno: TypeIdentifier) -> Expression {
Expression { id, kind, type_anno: Some(type_anno) } Expression { id, kind, type_anno: Some(type_anno) }
} }
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum TypeIdentifier { pub enum TypeIdentifier {
Tuple(Vec<TypeIdentifier>), Tuple(Vec<TypeIdentifier>),
Singleton(TypeSingletonName) Singleton(TypeSingletonName),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct TypeSingletonName { pub struct TypeSingletonName {
pub name: Rc<String>, pub name: Rc<String>,
pub params: Vec<TypeIdentifier>, pub params: Vec<TypeIdentifier>,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum ExpressionKind { pub enum ExpressionKind {
NatLiteral(u64), NatLiteral(u64),
FloatLiteral(f64), FloatLiteral(f64),
StringLiteral(Rc<String>), StringLiteral(Rc<String>),
BoolLiteral(bool), BoolLiteral(bool),
BinExp(BinOp, Box<Expression>, Box<Expression>), BinExp(BinOp, Box<Expression>, Box<Expression>),
PrefixExp(PrefixOp, Box<Expression>), PrefixExp(PrefixOp, Box<Expression>),
TupleLiteral(Vec<Expression>), TupleLiteral(Vec<Expression>),
Value(QualifiedName), Value(QualifiedName),
NamedStruct { NamedStruct { name: QualifiedName, fields: Vec<(Rc<String>, Expression)> },
name: QualifiedName, Call { f: Box<Expression>, arguments: Vec<InvocationArgument> },
fields: Vec<(Rc<String>, Expression)>, Index { indexee: Box<Expression>, indexers: Vec<Expression> },
}, IfExpression { discriminator: Option<Box<Expression>>, body: Box<IfExpressionBody> },
Call { WhileExpression { condition: Option<Box<Expression>>, body: Block },
f: Box<Expression>, ForExpression { enumerators: Vec<Enumerator>, body: Box<ForBody> },
arguments: Vec<InvocationArgument>, Lambda { params: Vec<FormalParam>, type_anno: Option<TypeIdentifier>, body: Block },
}, ListLiteral(Vec<Expression>),
Index {
indexee: Box<Expression>,
indexers: Vec<Expression>,
},
IfExpression {
discriminator: Option<Box<Expression>>,
body: Box<IfExpressionBody>,
},
WhileExpression {
condition: Option<Box<Expression>>,
body: Block,
},
ForExpression {
enumerators: Vec<Enumerator>,
body: Box<ForBody>,
},
Lambda {
params: Vec<FormalParam>,
type_anno: Option<TypeIdentifier>,
body: Block,
},
ListLiteral(Vec<Expression>),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum InvocationArgument { pub enum InvocationArgument {
Positional(Expression), Positional(Expression),
Keyword { Keyword { name: Rc<String>, expr: Expression },
name: Rc<String>, Ignored,
expr: Expression,
},
Ignored
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum IfExpressionBody { pub enum IfExpressionBody {
SimpleConditional { SimpleConditional { then_case: Block, else_case: Option<Block> },
then_case: Block, SimplePatternMatch { pattern: Pattern, then_case: Block, else_case: Option<Block> },
else_case: Option<Block> CondList(Vec<ConditionArm>),
},
SimplePatternMatch {
pattern: Pattern,
then_case: Block,
else_case: Option<Block>
},
CondList(Vec<ConditionArm>)
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct ConditionArm { pub struct ConditionArm {
pub condition: Condition, pub condition: Condition,
pub guard: Option<Expression>, pub guard: Option<Expression>,
pub body: Block, pub body: Block,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Condition { pub enum Condition {
Pattern(Pattern), Pattern(Pattern),
TruncatedOp(BinOp, Expression), TruncatedOp(BinOp, Expression),
Expression(Expression), Expression(Expression),
Else, Else,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Pattern { pub enum Pattern {
Ignored, Ignored,
TuplePattern(Vec<Pattern>), TuplePattern(Vec<Pattern>),
Literal(PatternLiteral), Literal(PatternLiteral),
TupleStruct(QualifiedName, Vec<Pattern>), TupleStruct(QualifiedName, Vec<Pattern>),
Record(QualifiedName, Vec<(Rc<String>, Pattern)>), Record(QualifiedName, Vec<(Rc<String>, Pattern)>),
VarOrName(QualifiedName), VarOrName(QualifiedName),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum PatternLiteral { pub enum PatternLiteral {
NumPattern { NumPattern { neg: bool, num: ExpressionKind },
neg: bool, StringPattern(Rc<String>),
num: ExpressionKind, BoolPattern(bool),
},
StringPattern(Rc<String>),
BoolPattern(bool),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Enumerator { pub struct Enumerator {
pub id: Rc<String>, pub id: Rc<String>,
pub generator: Expression, pub generator: Expression,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum ForBody { pub enum ForBody {
MonadicReturn(Expression), MonadicReturn(Expression),
StatementBlock(Block), StatementBlock(Block),
} }
#[derive(Debug, Derivative, Clone)] #[derive(Debug, Derivative, Clone)]
#[derivative(PartialEq)] #[derivative(PartialEq)]
pub struct ImportSpecifier { pub struct ImportSpecifier {
#[derivative(PartialEq="ignore")] #[derivative(PartialEq = "ignore")]
pub id: ItemId, pub id: ItemId,
pub path_components: Vec<Rc<String>>, pub path_components: Vec<Rc<String>>,
pub imported_names: ImportedNames pub imported_names: ImportedNames,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum ImportedNames { pub enum ImportedNames {
All, All,
LastOfPath, LastOfPath,
List(Vec<Rc<String>>) List(Vec<Rc<String>>),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct ModuleSpecifier { pub struct ModuleSpecifier {
pub name: Rc<String>, pub name: Rc<String>,
pub contents: Block, pub contents: Block,
} }

View File

@ -4,84 +4,84 @@ use crate::tokenizing::TokenKind;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct PrefixOp { pub struct PrefixOp {
sigil: Rc<String>, sigil: Rc<String>,
} }
impl PrefixOp { impl PrefixOp {
pub fn from_sigil(sigil: &str) -> PrefixOp { pub fn from_sigil(sigil: &str) -> PrefixOp {
PrefixOp { sigil: Rc::new(sigil.to_string()) } PrefixOp { sigil: Rc::new(sigil.to_string()) }
} }
pub fn sigil(&self) -> &str { pub fn sigil(&self) -> &str {
&self.sigil &self.sigil
} }
pub fn is_prefix(op: &str) -> bool { pub fn is_prefix(op: &str) -> bool {
matches!(op, "+" | "-" | "!") matches!(op, "+" | "-" | "!")
} }
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct BinOp { pub struct BinOp {
sigil: Rc<String>, sigil: Rc<String>,
} }
impl BinOp { impl BinOp {
pub fn from_sigil(sigil: &str) -> BinOp { pub fn from_sigil(sigil: &str) -> BinOp {
BinOp { sigil: Rc::new(sigil.to_string()) } BinOp { sigil: Rc::new(sigil.to_string()) }
} }
pub fn sigil(&self) -> &str { pub fn sigil(&self) -> &str {
&self.sigil &self.sigil
} }
pub fn from_sigil_token(tok: &TokenKind) -> Option<BinOp> { pub fn from_sigil_token(tok: &TokenKind) -> Option<BinOp> {
let s = token_kind_to_sigil(tok)?; let s = token_kind_to_sigil(tok)?;
Some(BinOp::from_sigil(s)) Some(BinOp::from_sigil(s))
} }
pub fn min_precedence() -> i32 { pub fn min_precedence() -> i32 {
i32::min_value() i32::min_value()
} }
pub fn get_precedence_from_token(op_tok: &TokenKind) -> Option<i32> { pub fn get_precedence_from_token(op_tok: &TokenKind) -> Option<i32> {
let s = token_kind_to_sigil(op_tok)?; let s = token_kind_to_sigil(op_tok)?;
Some(binop_precedences(s)) Some(binop_precedences(s))
} }
} }
fn token_kind_to_sigil(tok: & TokenKind) -> Option<&str> { fn token_kind_to_sigil(tok: &TokenKind) -> Option<&str> {
use self::TokenKind::*; use self::TokenKind::*;
Some(match tok { Some(match tok {
Operator(op) => op.as_str(), Operator(op) => op.as_str(),
Period => ".", Period => ".",
Pipe => "|", Pipe => "|",
Slash => "/", Slash => "/",
LAngleBracket => "<", LAngleBracket => "<",
RAngleBracket => ">", RAngleBracket => ">",
Equals => "=", Equals => "=",
_ => return None _ => return None,
}) })
} }
fn binop_precedences(s: &str) -> i32 { fn binop_precedences(s: &str) -> i32 {
let default = 10_000_000; let default = 10_000_000;
match s { match s {
"+" => 10, "+" => 10,
"-" => 10, "-" => 10,
"*" => 20, "*" => 20,
"/" => 20, "/" => 20,
"%" => 20, "%" => 20,
"++" => 30, "++" => 30,
"^" => 30, "^" => 30,
"&" => 20, "&" => 20,
"|" => 20, "|" => 20,
">" => 20, ">" => 20,
">=" => 20, ">=" => 20,
"<" => 20, "<" => 20,
"<=" => 20, "<=" => 20,
"==" => 40, "==" => 40,
"<=>" => 30, "<=>" => 30,
"=" => 5, // Assignment shoudl have highest precedence "=" => 5, // Assignment shoudl have highest precedence
_ => default, _ => default,
} }
} }

View File

@ -3,17 +3,27 @@ use crate::ast::*;
#[derive(Debug)] #[derive(Debug)]
pub enum Recursion { pub enum Recursion {
Continue, Continue,
Stop Stop,
} }
pub trait ASTVisitor: Sized { pub trait ASTVisitor: Sized {
fn expression(&mut self, _expression: &Expression) -> Recursion { Recursion::Continue } fn expression(&mut self, _expression: &Expression) -> Recursion {
fn declaration(&mut self, _declaration: &Declaration, _id: &ItemId) -> Recursion { Recursion::Continue } Recursion::Continue
}
fn declaration(&mut self, _declaration: &Declaration, _id: &ItemId) -> Recursion {
Recursion::Continue
}
fn import(&mut self, _import: &ImportSpecifier) -> Recursion { Recursion::Continue } fn import(&mut self, _import: &ImportSpecifier) -> Recursion {
fn module(&mut self, _module: &ModuleSpecifier) -> Recursion { Recursion::Continue } Recursion::Continue
}
fn module(&mut self, _module: &ModuleSpecifier) -> Recursion {
Recursion::Continue
}
fn pattern(&mut self, _pat: &Pattern) -> Recursion { Recursion::Continue } fn pattern(&mut self, _pat: &Pattern) -> Recursion {
Recursion::Continue
}
} }
pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) { pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
@ -32,12 +42,11 @@ pub fn walk_block<V: ASTVisitor>(v: &mut V, block: &Block) {
} }
Import(ref import_spec) => { Import(ref import_spec) => {
v.import(import_spec); v.import(import_spec);
}, }
Module(ref module_spec) => { Module(ref module_spec) =>
if let Recursion::Continue = v.module(module_spec) { if let Recursion::Continue = v.module(module_spec) {
walk_block(v, &module_spec.contents); walk_block(v, &module_spec.contents);
} },
}
} }
} }
} }
@ -50,12 +59,7 @@ pub fn walk_declaration<V: ASTVisitor>(v: &mut V, decl: &Declaration, id: &ItemI
FuncDecl(_sig, block) => { FuncDecl(_sig, block) => {
walk_block(v, block); walk_block(v, block);
} }
Binding { Binding { name: _, constant: _, type_anno: _, expr } => {
name: _,
constant: _,
type_anno: _,
expr,
} => {
walk_expression(v, expr); walk_expression(v, expr);
} }
_ => (), _ => (),
@ -76,16 +80,14 @@ pub fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
PrefixExp(_, arg) => { PrefixExp(_, arg) => {
walk_expression(v, arg); walk_expression(v, arg);
} }
TupleLiteral(exprs) => { TupleLiteral(exprs) =>
for expr in exprs { for expr in exprs {
walk_expression(v, expr); walk_expression(v, expr);
} },
} NamedStruct { name: _, fields } =>
NamedStruct { name: _, fields } => {
for (_, expr) in fields.iter() { for (_, expr) in fields.iter() {
walk_expression(v, expr); walk_expression(v, expr);
} },
}
Call { f, arguments } => { Call { f, arguments } => {
walk_expression(v, f); walk_expression(v, f);
for arg in arguments.iter() { for arg in arguments.iter() {
@ -102,10 +104,7 @@ pub fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
walk_expression(v, indexer); walk_expression(v, indexer);
} }
} }
IfExpression { IfExpression { discriminator, body } => {
discriminator,
body,
} => {
if let Some(d) = discriminator.as_ref() { if let Some(d) = discriminator.as_ref() {
walk_expression(v, d); walk_expression(v, d);
} }
@ -126,18 +125,13 @@ pub fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
ForBody::StatementBlock(block) => walk_block(v, block), ForBody::StatementBlock(block) => walk_block(v, block),
}; };
} }
Lambda { Lambda { params: _, type_anno: _, body } => {
params: _,
type_anno: _,
body,
} => {
walk_block(v, body); walk_block(v, body);
} }
ListLiteral(exprs) => { ListLiteral(exprs) =>
for expr in exprs { for expr in exprs {
walk_expression(v, expr); walk_expression(v, expr);
} },
}
}; };
} }
} }
@ -146,27 +140,20 @@ pub fn walk_if_expr_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
use IfExpressionBody::*; use IfExpressionBody::*;
match body { match body {
SimpleConditional { SimpleConditional { then_case, else_case } => {
then_case,
else_case,
} => {
walk_block(v, then_case); walk_block(v, then_case);
if let Some(block) = else_case.as_ref() { if let Some(block) = else_case.as_ref() {
walk_block(v, block) walk_block(v, block)
} }
} }
SimplePatternMatch { SimplePatternMatch { pattern, then_case, else_case } => {
pattern,
then_case,
else_case,
} => {
walk_pattern(v, pattern); walk_pattern(v, pattern);
walk_block(v, then_case); walk_block(v, then_case);
if let Some(block) = else_case.as_ref() { if let Some(block) = else_case.as_ref() {
walk_block(v, block) walk_block(v, block)
} }
} }
CondList(arms) => { CondList(arms) =>
for arm in arms { for arm in arms {
match arm.condition { match arm.condition {
Condition::Pattern(ref pat) => { Condition::Pattern(ref pat) => {
@ -184,8 +171,7 @@ pub fn walk_if_expr_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
walk_expression(v, guard); walk_expression(v, guard);
} }
walk_block(v, &arm.body); walk_block(v, &arm.body);
} },
}
} }
} }
@ -194,21 +180,18 @@ pub fn walk_pattern<V: ASTVisitor>(v: &mut V, pat: &Pattern) {
if let Recursion::Continue = v.pattern(pat) { if let Recursion::Continue = v.pattern(pat) {
match pat { match pat {
TuplePattern(patterns) => { TuplePattern(patterns) =>
for pat in patterns { for pat in patterns {
walk_pattern(v, pat); walk_pattern(v, pat);
} },
} TupleStruct(_, patterns) =>
TupleStruct(_, patterns) => {
for pat in patterns { for pat in patterns {
walk_pattern(v, pat); walk_pattern(v, pat);
} },
} Record(_, name_and_patterns) =>
Record(_, name_and_patterns) => {
for (_, pat) in name_and_patterns { for (_, pat) in name_and_patterns {
walk_pattern(v, pat); walk_pattern(v, pat);
} },
}
_ => (), _ => (),
}; };
} }