@@ -33,7 +33,8 @@ use crate::{
3333 solver:: { LinearExpr , Solver } ,
3434} ;
3535
36- pub const BUILTINS : [ & str ; 11 ] = [
36+ pub const BUILTINS : [ & str ; 12 ] = [
37+ "list" ,
3738 "cons" ,
3839 "head" ,
3940 "tail" ,
@@ -523,20 +524,20 @@ impl Ty {
523524
524525 /// Computes the least upper bound (LUB) of self and other.
525526 /// For use in type promotion.
526- pub fn lub ( & self , other : & Self ) -> Option < Self > {
527+ pub fn lub ( & self , other : & Self ) -> Self {
527528 match ( self , other) {
528529 // Unknown promotes to any type.
529- ( Ty :: Unknown , other) | ( other, Ty :: Unknown ) => Some ( other. clone ( ) ) ,
530+ ( Ty :: Unknown , other) | ( other, Ty :: Unknown ) => other. clone ( ) ,
531+ // At least one Any results in Any.
532+ ( Ty :: Any , _) | ( _, Ty :: Any ) => Ty :: Any ,
530533 // SeqNil promotes to any sequence type.
531- ( Ty :: SeqNil , Ty :: Seq ( inner) ) | ( Ty :: Seq ( inner) , Ty :: SeqNil ) => {
532- Some ( Ty :: Seq ( inner. clone ( ) ) )
533- }
534- // No other types promote.
534+ ( Ty :: SeqNil , Ty :: Seq ( inner) ) | ( Ty :: Seq ( inner) , Ty :: SeqNil ) => Ty :: Seq ( inner. clone ( ) ) ,
535+ // Mismatched types promote to any.
535536 ( a, b) => {
536537 if a == b {
537- Some ( a. clone ( ) )
538+ a. clone ( )
538539 } else {
539- None
540+ Ty :: Any
540541 }
541542 }
542543 }
@@ -1212,16 +1213,7 @@ impl<'a> AstTransformer for VarIdTyPass<'a> {
12121213 kind : StaticErrorKind :: IfCondNotBool ,
12131214 } ) ;
12141215 }
1215- let lub_ty = then_ty. lub ( & else_ty) ;
1216- if let Some ( lub_ty) = lub_ty {
1217- lub_ty
1218- } else {
1219- self . errors . push ( StaticError {
1220- span : self . span ( input. span ) ,
1221- kind : StaticErrorKind :: BranchesDifferentTypes ,
1222- } ) ;
1223- then_ty
1224- }
1216+ then_ty. lub ( & else_ty)
12251217 }
12261218
12271219 fn dispatch_match_expr (
@@ -1251,14 +1243,7 @@ impl<'a> AstTransformer for VarIdTyPass<'a> {
12511243 }
12521244
12531245 if let Some ( ref inner) = lub_ty {
1254- if let Some ( lub) = inner. lub ( & arm. expr . ty ( ) ) {
1255- lub_ty = Some ( lub) ;
1256- } else {
1257- self . errors . push ( StaticError {
1258- span : self . span ( arm. expr . span ( ) ) ,
1259- kind : StaticErrorKind :: BranchesDifferentTypes ,
1260- } ) ;
1261- }
1246+ lub_ty = Some ( inner. lub ( & arm. expr . ty ( ) ) ) ;
12621247 } else {
12631248 lub_ty = Some ( arm. expr . ty ( ) ) ;
12641249 }
@@ -1339,65 +1324,57 @@ impl<'a> AstTransformer for VarIdTyPass<'a> {
13391324 let left_ty = left. ty ( ) ;
13401325 let right_ty = right. ty ( ) ;
13411326 let lub_ty = left_ty. lub ( & right_ty) ;
1342- if let Some ( lub_ty) = lub_ty {
1343- if left_ty == Ty :: Float
1344- && ( input. op == ComparisonOp :: Eq || input. op == ComparisonOp :: Ne )
1345- {
1346- self . errors . push ( StaticError {
1347- span : self . span ( input. span ) ,
1348- kind : StaticErrorKind :: FloatEquality ,
1349- } ) ;
1350- }
1351- if matches ! ( left_ty, Ty :: Enum ( _) )
1352- && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1353- {
1354- self . errors . push ( StaticError {
1355- span : self . span ( input. span ) ,
1356- kind : StaticErrorKind :: EnumsNotOrd ,
1357- } ) ;
1358- }
1359- if matches ! ( left_ty, Ty :: Nil )
1360- && matches ! ( right_ty, Ty :: Nil )
1361- && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1362- {
1363- self . errors . push ( StaticError {
1364- span : self . span ( input. span ) ,
1365- kind : StaticErrorKind :: NilNotOrd ,
1366- } ) ;
1367- }
1368- if matches ! ( left_ty, Ty :: SeqNil )
1369- && matches ! ( right_ty, Ty :: SeqNil )
1370- && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1371- {
1372- self . errors . push ( StaticError {
1373- span : self . span ( input. span ) ,
1374- kind : StaticErrorKind :: SeqNilNotOrd ,
1375- } ) ;
1376- }
1377- if matches ! ( lub_ty, Ty :: Seq ( _) )
1378- && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1379- && !( left_ty == Ty :: SeqNil || right_ty == Ty :: SeqNil )
1380- {
1381- self . errors . push ( StaticError {
1382- span : self . span ( input. span ) ,
1383- kind : StaticErrorKind :: SeqMustCompareEqSeqNil ,
1384- } ) ;
1385- }
1386- if !matches ! (
1387- left_ty,
1388- Ty :: Float | Ty :: Int | Ty :: Enum ( _) | Ty :: Seq ( _) | Ty :: Nil | Ty :: SeqNil
1389- ) {
1390- self . errors . push ( StaticError {
1391- span : self . span ( input. span ) ,
1392- kind : StaticErrorKind :: ComparisonInvalidType ,
1393- } ) ;
1394- }
1395- } else {
1327+ if left_ty == Ty :: Float && ( input. op == ComparisonOp :: Eq || input. op == ComparisonOp :: Ne ) {
13961328 self . errors . push ( StaticError {
13971329 span : self . span ( input. span ) ,
1398- kind : StaticErrorKind :: BinOpMismatchedTypes ,
1330+ kind : StaticErrorKind :: FloatEquality ,
1331+ } ) ;
1332+ }
1333+ if matches ! ( left_ty, Ty :: Enum ( _) )
1334+ && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1335+ {
1336+ self . errors . push ( StaticError {
1337+ span : self . span ( input. span ) ,
1338+ kind : StaticErrorKind :: EnumsNotOrd ,
13991339 } ) ;
14001340 }
1341+ if matches ! ( left_ty, Ty :: Nil )
1342+ && matches ! ( right_ty, Ty :: Nil )
1343+ && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1344+ {
1345+ self . errors . push ( StaticError {
1346+ span : self . span ( input. span ) ,
1347+ kind : StaticErrorKind :: NilNotOrd ,
1348+ } ) ;
1349+ }
1350+ if matches ! ( left_ty, Ty :: SeqNil )
1351+ && matches ! ( right_ty, Ty :: SeqNil )
1352+ && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1353+ {
1354+ self . errors . push ( StaticError {
1355+ span : self . span ( input. span ) ,
1356+ kind : StaticErrorKind :: SeqNilNotOrd ,
1357+ } ) ;
1358+ }
1359+ if matches ! ( lub_ty, Ty :: Seq ( _) )
1360+ && ( input. op != ComparisonOp :: Eq && input. op != ComparisonOp :: Ne )
1361+ && !( left_ty == Ty :: SeqNil || right_ty == Ty :: SeqNil )
1362+ {
1363+ self . errors . push ( StaticError {
1364+ span : self . span ( input. span ) ,
1365+ kind : StaticErrorKind :: SeqMustCompareEqSeqNil ,
1366+ } ) ;
1367+ }
1368+ if !matches ! (
1369+ left_ty,
1370+ Ty :: Float | Ty :: Int | Ty :: Enum ( _) | Ty :: Seq ( _) | Ty :: Nil | Ty :: SeqNil
1371+ ) {
1372+ self . errors . push ( StaticError {
1373+ span : self . span ( input. span ) ,
1374+ kind : StaticErrorKind :: ComparisonInvalidType ,
1375+ } ) ;
1376+ }
1377+
14011378 Ty :: Bool
14021379 }
14031380
@@ -1530,6 +1507,24 @@ impl<'a> AstTransformer for VarIdTyPass<'a> {
15301507 ( None , Ty :: SeqNil )
15311508 }
15321509 }
1510+ "list" => {
1511+ self . typecheck_kwargs ( & args. kwargs , IndexMap :: default ( ) ) ;
1512+ if args. posargs . is_empty ( ) {
1513+ self . errors . push ( StaticError {
1514+ span : self . span ( input. span ) ,
1515+ kind : StaticErrorKind :: EmptyListConstructor ,
1516+ } ) ;
1517+ ( None , Ty :: Nil )
1518+ } else {
1519+ let elem_ty = args
1520+ . posargs
1521+ . iter ( )
1522+ . map ( Expr :: ty)
1523+ . reduce ( |acc, e| acc. lub ( & e) )
1524+ . unwrap ( ) ;
1525+ ( None , Ty :: Seq ( Box :: new ( elem_ty) ) )
1526+ }
1527+ }
15331528 "head" => {
15341529 self . assert_eq_arity ( input. span , args. posargs . len ( ) , 1 ) ;
15351530 if args. posargs . len ( ) == 1 {
@@ -2844,7 +2839,12 @@ impl<'a> ExecPass<'a> {
28442839 Expr :: BinOp ( b) => {
28452840 let lhs = self . visit_expr ( loc, & b. left ) ;
28462841 let rhs = self . visit_expr ( loc, & b. right ) ;
2847- PartialEvalState :: BinOp ( PartialBinOp { lhs, rhs, op : b. op } )
2842+ PartialEvalState :: BinOp ( PartialBinOp {
2843+ lhs,
2844+ rhs,
2845+ op : b. op ,
2846+ expr : b. clone ( ) ,
2847+ } )
28482848 }
28492849 Expr :: UnaryOp ( u) => {
28502850 let operand = self . visit_expr ( loc, & u. operand ) ;
@@ -3179,6 +3179,23 @@ impl<'a> ExecPass<'a> {
31793179 false
31803180 }
31813181 }
3182+ "list" => {
3183+ let vals = c
3184+ . state
3185+ . posargs
3186+ . iter ( )
3187+ . map ( |v| self . values [ v] . get_ready ( ) )
3188+ . collect :: < Option < Vec < _ > > > ( ) ;
3189+ if let Some ( vals) = vals {
3190+ self . values . insert (
3191+ vid,
3192+ Defer :: Ready ( Value :: Seq ( vals. iter ( ) . map ( |v| ( * v) . clone ( ) ) . collect ( ) ) ) ,
3193+ ) ;
3194+ true
3195+ } else {
3196+ false
3197+ }
3198+ }
31823199 "head" => {
31833200 if let Defer :: Ready ( head) = & self . values [ & c. state . posargs [ 0 ] ] {
31843201 let val = match head {
@@ -3473,7 +3490,15 @@ impl<'a> ExecPass<'a> {
34733490 self . values . insert ( vid, DeferValue :: Ready ( Value :: Int ( res) ) ) ;
34743491 true
34753492 }
3476- _ => todo ! ( ) ,
3493+ _ => {
3494+ let span = self . span ( & vref. loc , bin_op. expr . span ) ;
3495+ self . errors . push ( ExecError {
3496+ span : Some ( span. clone ( ) ) ,
3497+ cell : vref. loc . cell ,
3498+ kind : ExecErrorKind :: InvalidType ,
3499+ } ) ;
3500+ return Err ( ( ) ) ;
3501+ }
34773502 }
34783503 } else {
34793504 false
@@ -4336,6 +4361,9 @@ pub enum StaticErrorKind {
43364361 /// Incorrect type category.
43374362 #[ error( "expected type category {expected}, found {found:?}" ) ]
43384363 IncorrectTyCategory { found : Ty , expected : String } ,
4364+ /// Empty list constructor.
4365+ #[ error( "list constructors cannot be empty (use `[]` for an empty list)" ) ]
4366+ EmptyListConstructor ,
43394367 /// Called a function or cell with the wrong number of positional arguments.
43404368 #[ error( "expected {expected} position arguments, found {found}" ) ]
43414369 CallIncorrectPositionalArity { expected : usize , found : usize } ,
@@ -4462,7 +4490,7 @@ enum PartialEvalState<T: AstMetadata> {
44624490 If ( Box < PartialIfExpr < T > > ) ,
44634491 Match ( Box < PartialMatchExpr < T > > ) ,
44644492 Comparison ( Box < PartialComparisonExpr < T > > ) ,
4465- BinOp ( PartialBinOp ) ,
4493+ BinOp ( PartialBinOp < T > ) ,
44664494 UnaryOp ( PartialUnaryOp < T > ) ,
44674495 Call ( Box < PartialCallExpr < T > > ) ,
44684496 FieldAccess ( Box < PartialFieldAccessExpr < T > > ) ,
@@ -4487,10 +4515,11 @@ struct PartialConstraint {
44874515}
44884516
44894517#[ derive( Debug , Clone ) ]
4490- struct PartialBinOp {
4518+ struct PartialBinOp < T : AstMetadata > {
44914519 lhs : ValueId ,
44924520 rhs : ValueId ,
44934521 op : BinOp ,
4522+ expr : Box < BinOpExpr < Substr , T > > ,
44944523}
44954524
44964525#[ derive( Debug , Clone ) ]
0 commit comments