From 8d2facca358d54dc03d8b04872c9e6015e047d6a Mon Sep 17 00:00:00 2001 From: Aaron Councilman <aaronjc4@illinois.edu> Date: Fri, 31 Jan 2025 08:39:21 -0600 Subject: [PATCH] Juno patterns --- Cargo.lock | 10 + Cargo.toml | 1 + juno_frontend/src/lang.l | 1 + juno_frontend/src/lang.y | 33 +- juno_frontend/src/semant.rs | 584 +++++++++++++++++--------- juno_frontend/src/types.rs | 36 +- juno_samples/antideps/src/antideps.jn | 2 +- juno_samples/patterns/Cargo.toml | 18 + juno_samples/patterns/build.rs | 9 + juno_samples/patterns/src/main.rs | 19 + juno_samples/patterns/src/patterns.jn | 12 + 11 files changed, 498 insertions(+), 227 deletions(-) create mode 100644 juno_samples/patterns/Cargo.toml create mode 100644 juno_samples/patterns/build.rs create mode 100644 juno_samples/patterns/src/main.rs create mode 100644 juno_samples/patterns/src/patterns.jn diff --git a/Cargo.lock b/Cargo.lock index d6ebd2f7..2802b8b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1134,6 +1134,16 @@ dependencies = [ "with_builtin_macros", ] +[[package]] +name = "juno_patterns" +version = "0.1.0" +dependencies = [ + "async-std", + "hercules_rt", + "juno_build", + "with_builtin_macros", +] + [[package]] name = "juno_schedule_test" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index d31c59f7..a9197bf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ members = [ "hercules_samples/ccp", "juno_samples/simple3", + "juno_samples/patterns", "juno_samples/matmul", "juno_samples/casts_and_intrinsics", "juno_samples/nested_ccp", diff --git a/juno_frontend/src/lang.l b/juno_frontend/src/lang.l index d54a54d7..94a12002 100644 --- a/juno_frontend/src/lang.l +++ b/juno_frontend/src/lang.l @@ -107,6 +107,7 @@ void "void" : ":" , "," +\.\. ".." \. "." ; ";" ~ "~" diff --git a/juno_frontend/src/lang.y b/juno_frontend/src/lang.y index e980773f..b47186ff 100644 --- a/juno_frontend/src/lang.y +++ b/juno_frontend/src/lang.y @@ -197,8 +197,10 @@ Pattern -> Result<Pattern, ()> Ok(Pattern::IntLit { span : span, base : base }) } | PackageName { Ok(Pattern::Variable { span : $span, name : $1? }) } | '(' PatternsComma ')' { Ok(Pattern::TuplePattern { span : $span, pats : $2? }) } - | PackageName '{' NamePatterns '}' - { Ok(Pattern::StructPattern { span : $span, name : $1?, pats : $3? }) } + | PackageName '{' StructPatterns '}' + { let (pats, ignore_other) = $3?; + let pats = pats.into_iter().collect(); + Ok(Pattern::StructPattern { span : $span, name : $1?, pats, ignore_other }) } | PackageName '(' PatternsComma ')' { Ok(Pattern::UnionPattern { span : $span, name : $1?, pats : $3? }) } ; @@ -211,13 +213,23 @@ PatternsCommaS -> Result<Vec<Pattern>, ()> : Pattern { Ok(vec![$1?]) } | PatternsCommaS ',' Pattern { flatten($1, $3) } ; -NamePatterns -> Result<Vec<(Id, Pattern)>, ()> - : 'ID' ':' Pattern { Ok(vec![(span_of_tok($1)?, $3?)]) } - | NamePatternsS ',' 'ID' ':' Pattern { flatten($1, res_pair(span_of_tok($3), $5)) } - ; -NamePatternsS -> Result<Vec<(Id, Pattern)>, ()> - : 'ID' ':' Pattern { Ok(vec![(span_of_tok($1)?, $3?)]) } - | NamePatternsS ',' 'ID' ':' Pattern { flatten($1, res_pair(span_of_tok($3), $5)) } +StructPatterns -> Result<(VecDeque<(Id, Pattern)>, bool), ()> + : { Ok((VecDeque::new(), false)) } + | '..' { Ok((VecDeque::new(), true)) } + | 'ID' { let span = span_of_tok($1)?; + let pattern = Pattern::Variable { span, name: vec![span] }; + Ok((VecDeque::from([(span, pattern)]), false)) } + | 'ID' ':' Pattern { let span = span_of_tok($1)?; + Ok((VecDeque::from([(span, $3?)]), false)) } + | 'ID' ',' StructPatterns { let span = span_of_tok($1)?; + let pattern = Pattern::Variable { span, name: vec![span] }; + let (mut fields, ignore_rest) = $3?; + fields.push_front((span, pattern)); + Ok((fields, ignore_rest)) } + | 'ID' ':' Pattern ',' StructPatterns { let span = span_of_tok($1)?; + let (mut fields, ignore_rest) = $5?; + fields.push_front((span, $3?)); + Ok((fields, ignore_rest)) } ; Stmt -> Result<Stmt, ()> @@ -683,7 +695,8 @@ pub enum Pattern { IntLit { span : Span, base : IntBase }, Variable { span : Span, name : PackageName }, TuplePattern { span : Span, pats : Vec<Pattern> }, - StructPattern { span : Span, name : PackageName, pats : Vec<(Id, Pattern)> }, + // Ignore other indicates the pattern ended with .. and so there may be other fields that were not listed + StructPattern { span : Span, name : PackageName, pats : Vec<(Id, Pattern)>, ignore_other: bool }, UnionPattern { span : Span, name : PackageName, pats : Vec<Pattern> }, } diff --git a/juno_frontend/src/semant.rs b/juno_frontend/src/semant.rs index 2fe4bf88..e133e3c2 100644 --- a/juno_frontend/src/semant.rs +++ b/juno_frontend/src/semant.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, LinkedList}; +use std::collections::{HashMap, HashSet, LinkedList}; use std::fmt; use std::fs::File; use std::io::Read; @@ -720,52 +720,49 @@ fn analyze_program( } // Process arguments - let mut arg_types: Vec<(usize, Type, bool)> = vec![]; // list of name, type, and - // whether is inout - let mut inout_args = vec![]; // list of indices into args + // We collect the list of the argument types, whether they are inout, and their + // unique variable number + let mut arg_info: Vec<(Type, bool, usize)> = vec![]; + // We collect the list of the types and variable numbers of the inout arguments + let mut inouts: Vec<(Type, usize)> = vec![]; // A collection of errors we encounter processing the arguments let mut errors = LinkedList::new(); + // Any statements that need to go at the beginning of the function to handle + // patterns in the arguments + let mut stmts = vec![]; for (inout, VarBind { span, pattern, typ }) in args { let typ = typ.unwrap_or(parser::Type::WildType { span }); - match pattern { - Pattern::Variable { span, name } => { - if name.len() != 1 { - errors.push_back( - ErrorMessage::SemanticError( - span_to_loc(span, lexer), - "Bound variables must be local names, without a package separator".to_string())); - continue; + match process_type( + typ, + num_dyn_const, + lexer, + &mut stringtab, + &env, + &mut types, + true, + ) { + Ok(ty) => { + let var = env.uniq(); + + if inout.is_some() { + inouts.push((ty, var)); } + arg_info.push((ty, inout.is_some(), var)); - let nm = intern_package_name(&name, lexer, &mut stringtab)[0]; - match process_type( - typ, - num_dyn_const, - lexer, - &mut stringtab, - &env, - &mut types, - true, - ) { - Ok(ty) => { - if inout.is_some() { - inout_args.push(arg_types.len()); - } - arg_types.push((nm, ty, inout.is_some())); + match process_irrefutable_pattern(pattern, false, var, ty, lexer, &mut stringtab, &mut env, &mut types) { + Ok(prep) => { + stmts.extend(prep); } Err(mut errs) => { errors.append(&mut errs); } } } - _ => { - errors.push_back(ErrorMessage::NotImplemented( - span_to_loc(span, lexer), - "patterns in arguments".to_string(), - )); + Err(mut errs) => { + errors.append(&mut errs); } } } @@ -798,34 +795,12 @@ fn analyze_program( } // Compute the proper type accounting for the inouts (which become returns) - let mut inout_types = vec![]; - for arg_idx in &inout_args { - inout_types.push(arg_types[*arg_idx].1.clone()); - } + let mut inout_types = inouts.iter().map(|(t, _)| *t).collect::<Vec<_>>(); let inout_tuple = types.new_tuple(inout_types.clone()); let pure_return_type = types.new_tuple(vec![return_type, inout_tuple]); - // Add the arguments to the environment and assign each a unique variable number - // Also track the variable numbers of the inout arguments for generating returns - let mut arg_variables = vec![]; - let mut inout_variables = vec![]; - for (nm, ty, is_inout) in arg_types.iter() { - let variable = env.uniq(); - env.insert( - *nm, - Entity::Variable { - variable: variable, - typ: *ty, - is_const: false, - }, - ); - arg_variables.push(variable); - - if *is_inout { - inout_variables.push(variable); - } - } + let inout_variables = inouts.iter().map(|(_, v)| *v).collect::<Vec<_>>(); // Finally, we have a properly built environment and we can // start processing the body @@ -871,6 +846,10 @@ fn analyze_program( } } + // Add the code for initializing arguments + stmts.push(body); + body = Stmt::BlockStmt { body: stmts }; + env.close_scope(); // Add the function to the global environment @@ -880,9 +859,9 @@ fn analyze_program( Entity::Function { index: res.len(), type_args: type_kinds, - args: arg_types + args: arg_info .iter() - .map(|(_, ty, is)| (*ty, *is)) + .map(|(ty, is, _)| (*ty, *is)) .collect::<Vec<_>>(), return_type: return_type, }, @@ -893,10 +872,9 @@ fn analyze_program( name: lexer.span_str(name).to_string(), num_dyn_consts: num_dyn_const, num_type_args: num_type_var, - arguments: arg_types + arguments: arg_info .iter() - .zip(arg_variables.iter()) - .map(|(v, n)| (*n, v.1)) + .map(|(t, _, v)| (*v, *t)) .collect::<Vec<_>>(), return_type: pure_return_type, body: body, @@ -1626,7 +1604,7 @@ fn process_stmt( ) -> Result<(Stmt, bool), ErrorMessages> { match stmt { parser::Stmt::LetStmt { - span: _, + span, var: VarBind { span: v_span, @@ -1634,82 +1612,66 @@ fn process_stmt( typ, }, init, - } => match pattern { - Pattern::Variable { span, name } => { - if typ.is_none() && init.is_none() { - Err(singleton_error(ErrorMessage::SemanticError( - span_to_loc(span, lexer), - "Must specify either type or initial value".to_string(), - )))? - } - if name.len() != 1 { - Err(singleton_error(ErrorMessage::SemanticError( - span_to_loc(span, lexer), - "Bound variables must be local names, without a package separator" - .to_string(), - )))? - } - - let nm = intern_package_name(&name, lexer, stringtab)[0]; - let ty = match typ { - None => None, - Some(t) => Some(process_type( - t, - num_dyn_const, - lexer, - stringtab, - env, - types, - true, - )?), - }; + } => { + if typ.is_none() && init.is_none() { + return Err(singleton_error(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + "Must specify either type or initial value".to_string(), + ))); + } - let var = env.uniq(); + let ty = match typ { + None => None, + Some(t) => Some(process_type( + t, + num_dyn_const, + lexer, + stringtab, + env, + types, + true, + )?), + }; - let (val, exp_loc) = match init { - Some(exp) => { - let loc = span_to_loc(exp.span(), lexer); - ( - process_expr(exp, num_dyn_const, lexer, stringtab, env, types)?, - loc, - ) - } - None => ( - Expr::Zero { - typ: ty.expect("From Above"), - }, - Location::fake(), - ), - }; - let typ = val.get_type(); + let var = env.uniq(); - env.insert( - nm, - Entity::Variable { - variable: var, - typ: typ, - is_const: false, + let (val, exp_loc) = match init { + Some(exp) => { + let loc = span_to_loc(exp.span(), lexer); + ( + process_expr(exp, num_dyn_const, lexer, stringtab, env, types)?, + loc, + ) + } + None => ( + Expr::Zero { + typ: ty.expect("From Above"), }, - ); + Location::fake(), + ), + }; + let typ = val.get_type(); - match ty { - Some(ty) if !types.unify(ty, typ) => { - Err(singleton_error(ErrorMessage::TypeError( - exp_loc, - unparse_type(types, ty, stringtab), - unparse_type(types, typ, stringtab), - )))? - } - _ => Ok((Stmt::AssignStmt { var: var, val: val }, true)), + if let Some(ty) = ty { + if !types.unify(ty, typ) { + return Err(singleton_error(ErrorMessage::TypeError( + exp_loc, + unparse_type(types, ty, stringtab), + unparse_type(types, typ, stringtab), + ))); } } - _ => Err(singleton_error(ErrorMessage::NotImplemented( - span_to_loc(v_span, lexer), - "non-variable bindings".to_string(), - ))), - }, + + let mut res = vec![]; + res.push(Stmt::AssignStmt { var, val }); + res.extend(process_irrefutable_pattern( + pattern, false, var, typ, lexer, stringtab, env, types, + )?); + + Ok((Stmt::BlockStmt { body: res }, true)) + } parser::Stmt::ConstStmt { - span: _, + span, var: VarBind { span: v_span, @@ -1717,80 +1679,64 @@ fn process_stmt( typ, }, init, - } => match pattern { - Pattern::Variable { span, name } => { - if typ.is_none() && init.is_none() { - Err(singleton_error(ErrorMessage::SemanticError( - span_to_loc(span, lexer), - "Must specify either type or initial value".to_string(), - )))? - } - if name.len() != 1 { - Err(singleton_error(ErrorMessage::SemanticError( - span_to_loc(span, lexer), - "Bound variables must be local names, without a package separator" - .to_string(), - )))? - } - - let nm = intern_package_name(&name, lexer, stringtab)[0]; - let ty = match typ { - None => None, - Some(t) => Some(process_type( - t, - num_dyn_const, - lexer, - stringtab, - env, - types, - true, - )?), - }; + } => { + if typ.is_none() && init.is_none() { + return Err(singleton_error(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + "Must specify either type or initial value".to_string(), + ))); + } - let var = env.uniq(); + let ty = match typ { + None => None, + Some(t) => Some(process_type( + t, + num_dyn_const, + lexer, + stringtab, + env, + types, + true, + )?), + }; - let (val, exp_loc) = match init { - Some(exp) => { - let loc = span_to_loc(exp.span(), lexer); - ( - process_expr(exp, num_dyn_const, lexer, stringtab, env, types)?, - loc, - ) - } - None => ( - Expr::Zero { - typ: ty.expect("From Above"), - }, - Location::fake(), - ), - }; - let typ = val.get_type(); + let var = env.uniq(); - env.insert( - nm, - Entity::Variable { - variable: var, - typ: typ, - is_const: true, + let (val, exp_loc) = match init { + Some(exp) => { + let loc = span_to_loc(exp.span(), lexer); + ( + process_expr(exp, num_dyn_const, lexer, stringtab, env, types)?, + loc, + ) + } + None => ( + Expr::Zero { + typ: ty.expect("From Above"), }, - ); + Location::fake(), + ), + }; + let typ = val.get_type(); - match ty { - Some(ty) if !types.unify(ty, typ) => { - Err(singleton_error(ErrorMessage::TypeError( - exp_loc, - unparse_type(types, ty, stringtab), - unparse_type(types, typ, stringtab), - ))) - } - _ => Ok((Stmt::AssignStmt { var: var, val: val }, true)), + if let Some(ty) = ty { + if !types.unify(ty, typ) { + return Err(singleton_error(ErrorMessage::TypeError( + exp_loc, + unparse_type(types, ty, stringtab), + unparse_type(types, typ, stringtab), + ))); } } - _ => Err(singleton_error(ErrorMessage::NotImplemented( - span_to_loc(v_span, lexer), - "non-variable bindings".to_string(), - ))), - }, + + let mut res = vec![]; + res.push(Stmt::AssignStmt { var, val }); + res.extend(process_irrefutable_pattern( + pattern, false, var, typ, lexer, stringtab, env, types, + )?); + + Ok((Stmt::BlockStmt { body: res }, true)) + } parser::Stmt::AssignStmt { span: _, lhs, @@ -2070,9 +2016,9 @@ fn process_stmt( (var, nm, var_type) } _ => { - return Err(singleton_error(ErrorMessage::NotImplemented( + return Err(singleton_error(ErrorMessage::SemanticError( span_to_loc(v_span, lexer), - "patterns in for loop arguments".to_string(), + "for loop index must be a variable".to_string(), ))); } }; @@ -5107,3 +5053,243 @@ fn convert_primitive(prim: parser::Primitive) -> types::Primitive { parser::Primitive::Void => types::Primitive::Unit, } } + +// Processes an irrefutable pattern by extracting the pieces from the given variable which has the +// given type. Adds any variables in that pattern to the environment and returns a list of +// statements that handle the pattern +fn process_irrefutable_pattern( + pat: parser::Pattern, + is_const: bool, + var: usize, + typ: Type, + lexer: &dyn NonStreamingLexer<DefaultLexerTypes<u32>>, + stringtab: &mut StringTable, + env: &mut Env<usize, Entity>, + types: &mut TypeSolver, +) -> Result<Vec<Stmt>, ErrorMessages> { + match pat { + Pattern::Wildcard { .. } => Ok(vec![]), + Pattern::Variable { span, name } => { + if name.len() != 1 { + return Err(singleton_error(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + "Bound variables must be local names, without a package separator".to_string(), + ))); + } + + let nm = intern_package_name(&name, lexer, stringtab)[0]; + let variable = env.uniq(); + env.insert( + nm, + Entity::Variable { + variable, + typ, + is_const, + }, + ); + + Ok(vec![Stmt::AssignStmt { + var: variable, + val: Expr::Variable { var, typ }, + }]) + } + Pattern::TuplePattern { span, pats } => { + let Some(fields) = types.get_fields(typ) else { + return Err(singleton_error(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + format!( + "Type {} is not a tuple", + unparse_type(types, typ, stringtab), + ), + ))); + }; + let fields = fields.clone(); + + if fields.len() != pats.len() { + return Err(singleton_error(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + format!( + "Expected {} fields, pattern has {}", + fields.len(), + pats.len() + ), + ))); + } + + let mut res = vec![]; + let mut errors = LinkedList::new(); + + for (idx, (pat, field)) in pats.into_iter().zip(fields.into_iter()).enumerate() { + // Extract this field from the current value + let variable = env.uniq(); + res.push(Stmt::AssignStmt { + var: variable, + val: Expr::Read { + index: vec![Index::Field(idx)], + val: Box::new(Expr::Variable { var, typ }), + typ: field, + }, + }); + + match process_irrefutable_pattern( + pat, is_const, variable, field, lexer, stringtab, env, types, + ) { + Ok(stmts) => res.extend(stmts), + Err(errs) => errors.extend(errs), + } + } + + if errors.is_empty() { + Ok(res) + } else { + Err(errors) + } + } + Pattern::StructPattern { + span, + name, + pats, + ignore_other, + } => { + if name.len() != 1 { + return Err(singleton_error(ErrorMessage::NotImplemented( + span_to_loc(span, lexer), + "packages".to_string(), + ))); + } + + let struct_nm = intern_package_name(&name, lexer, stringtab)[0]; + match env.lookup(&struct_nm) { + Some(Entity::Variable { .. }) => Err(singleton_error(ErrorMessage::KindError( + span_to_loc(span, lexer), + "struct name".to_string(), + "variable".to_string(), + ))), + Some(Entity::DynConst { .. }) => Err(singleton_error(ErrorMessage::KindError( + span_to_loc(span, lexer), + "struct name".to_string(), + "dynamic constant".to_string(), + ))), + Some(Entity::Constant { .. }) => Err(singleton_error(ErrorMessage::KindError( + span_to_loc(span, lexer), + "struct name".to_string(), + "constant".to_string(), + ))), + Some(Entity::Function { .. }) => Err(singleton_error(ErrorMessage::KindError( + span_to_loc(span, lexer), + "struct name".to_string(), + "function".to_string(), + ))), + None => Err(singleton_error(ErrorMessage::UndefinedVariable( + span_to_loc(span, lexer), + stringtab.lookup_id(struct_nm).unwrap(), + ))), + Some(Entity::Type { + type_args: _, + value: struct_typ, + }) => { + let struct_typ = *struct_typ; + + if !types.is_struct(struct_typ) { + return Err(singleton_error(ErrorMessage::KindError( + span_to_loc(span, lexer), + "struct name".to_string(), + "non-struct type".to_string(), + ))); + } + + if !types.unify(typ, struct_typ) { + return Err(singleton_error(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + format!( + "Expected a pattern for type {} but found pattern for type {}", + unparse_type(types, typ, stringtab), + unparse_type(types, struct_typ, stringtab) + ), + ))); + } + + // Fields that have already been used + let mut unused_fields = types + .get_field_names(struct_typ) + .unwrap() + .into_iter() + .collect::<HashSet<_>>(); + let mut res = vec![]; + let mut errors = LinkedList::new(); + + for (field_name, pat) in pats { + let field_nm = intern_id(&field_name, lexer, stringtab); + match types.get_field(struct_typ, field_nm) { + None => { + errors.push_back(ErrorMessage::SemanticError( + span_to_loc(field_name, lexer), + format!( + "Struct {} does not have field {}", + unparse_type(types, struct_typ, stringtab), + stringtab.lookup_id(field_nm).unwrap() + ), + )); + } + Some((idx, field_typ)) => { + if !unused_fields.contains(&field_nm) { + errors.push_back(ErrorMessage::SemanticError( + span_to_loc(field_name, lexer), + format!( + "Field {} appears multiple times in pattern", + stringtab.lookup_id(field_nm).unwrap() + ), + )); + } else { + unused_fields.remove(&field_nm); + let variable = env.uniq(); + res.push(Stmt::AssignStmt { + var: variable, + val: Expr::Read { + index: vec![Index::Field(idx)], + val: Box::new(Expr::Variable { var, typ }), + typ: field_typ, + }, + }); + match process_irrefutable_pattern( + pat, is_const, variable, field_typ, lexer, stringtab, env, + types, + ) { + Ok(stmts) => res.extend(stmts), + Err(errs) => errors.extend(errs), + } + } + } + } + } + + if !unused_fields.is_empty() && !ignore_other { + errors.push_back(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + format!( + "Pattern is missing fields: {}", + unused_fields + .into_iter() + .map(|i| stringtab.lookup_id(i).unwrap()) + .collect::<Vec<_>>() + .join(", ") + ), + )); + } + + if !errors.is_empty() { + Err(errors) + } else { + Ok(res) + } + } + } + } + Pattern::IntLit { span, .. } | Pattern::UnionPattern { span, .. } => { + Err(singleton_error(ErrorMessage::SemanticError( + span_to_loc(span, lexer), + "Expected an irrefutable pattern, but pattern is refutable".to_string(), + ))) + } + } +} diff --git a/juno_frontend/src/types.rs b/juno_frontend/src/types.rs index 5f907cd9..d4d8b233 100644 --- a/juno_frontend/src/types.rs +++ b/juno_frontend/src/types.rs @@ -556,15 +556,16 @@ impl TypeSolver { _ => None, } } + */ - fn get_fields(&self, Type { val } : Type) -> Vec<Type> { - match &self.types[val] { - TypeForm::Tuple(fields) => { fields.clone() }, - TypeForm::OtherType(t) => self.get_fields(*t), - _ => panic!("Internal function get_fields used on non-tuple"), - } + // Returns the types of the fields of a tuple + pub fn get_fields(&self, Type { val }: Type) -> Option<&Vec<Type>> { + match &self.types[val] { + TypeForm::Tuple { fields, .. } => Some(fields), + TypeForm::OtherType { other, .. } => self.get_fields(*other), + _ => None, } - */ + } // Return the type of the field (in a tuple) at a particular index pub fn get_index(&self, Type { val }: Type, idx: usize) -> Option<Type> { @@ -626,17 +627,18 @@ impl TypeSolver { } } - /* - pub fn get_field_names(&self, Type { val } : Type) -> Option<Vec<usize>> { - match &self.types[val] { - TypeForm::Struct { name : _, id : _, fields : _, names } => { - Some(names.keys().map(|i| *i).collect::<Vec<_>>()) - }, - TypeForm::OtherType(t) => self.get_field_names(*t), - _ => None, - } + pub fn get_field_names(&self, Type { val }: Type) -> Option<Vec<usize>> { + match &self.types[val] { + TypeForm::Struct { + name: _, + id: _, + fields: _, + names, + } => Some(names.keys().map(|i| *i).collect::<Vec<_>>()), + TypeForm::OtherType { other, .. } => self.get_field_names(*other), + _ => None, } - */ + } pub fn get_num_dimensions(&self, Type { val }: Type) -> Option<usize> { match &self.types[val] { diff --git a/juno_samples/antideps/src/antideps.jn b/juno_samples/antideps/src/antideps.jn index f40640d2..85c8b9d4 100644 --- a/juno_samples/antideps/src/antideps.jn +++ b/juno_samples/antideps/src/antideps.jn @@ -114,7 +114,7 @@ fn very_complex_antideps(x: usize) -> usize { #[entry] fn read_chains(input : i32) -> i32 { let arrs : (i32[2], i32[2]); - let sub = arrs.0; + let (sub, _) = arrs; sub[1] = input + 7; arrs.0[1] = input + 3; let result = sub[1] + arrs.0[1]; diff --git a/juno_samples/patterns/Cargo.toml b/juno_samples/patterns/Cargo.toml new file mode 100644 index 00000000..a8dda157 --- /dev/null +++ b/juno_samples/patterns/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "juno_patterns" +version = "0.1.0" +authors = ["Aaron Councilman <aaronjc4@illinois.edu>"] +edition = "2021" + +[[bin]] +name = "juno_patterns" +path = "src/main.rs" + +[build-dependencies] +juno_build = { path = "../../juno_build" } + +[dependencies] +juno_build = { path = "../../juno_build" } +hercules_rt = { path = "../../hercules_rt" } +with_builtin_macros = "0.1.0" +async-std = "*" diff --git a/juno_samples/patterns/build.rs b/juno_samples/patterns/build.rs new file mode 100644 index 00000000..8ac92f00 --- /dev/null +++ b/juno_samples/patterns/build.rs @@ -0,0 +1,9 @@ +use juno_build::JunoCompiler; + +fn main() { + JunoCompiler::new() + .file_in_src("patterns.jn") + .unwrap() + .build() + .unwrap(); +} diff --git a/juno_samples/patterns/src/main.rs b/juno_samples/patterns/src/main.rs new file mode 100644 index 00000000..5cc2e7c8 --- /dev/null +++ b/juno_samples/patterns/src/main.rs @@ -0,0 +1,19 @@ +#![feature(concat_idents)] + +use hercules_rt::{runner}; + +juno_build::juno!("patterns"); + +fn main() { + async_std::task::block_on(async { + let mut r = runner!(entry); + let c = r.run(3, 8.0).await; + println!("{}", c); + assert_eq!(c, 14.0); + }); +} + +#[test] +fn simple3_test() { + main(); +} diff --git a/juno_samples/patterns/src/patterns.jn b/juno_samples/patterns/src/patterns.jn new file mode 100644 index 00000000..923c258d --- /dev/null +++ b/juno_samples/patterns/src/patterns.jn @@ -0,0 +1,12 @@ +type Record = struct { a: i32; b: f64; }; + +#[entry] +fn entry(x: i32, f: f64) -> f64 { + let r = Record { a=x, b=f }; + let p = (f, f, x); + + let Record { a, .. } = r; + let (_, b, c) = p; + + return (a + c) as f64 + b; +} -- GitLab