From 1afe1643c0a1689f4e0257ff88b3b9d7368d1367 Mon Sep 17 00:00:00 2001 From: Sei Lisa Date: Mon, 9 Apr 2018 18:42:31 +0200 Subject: [PATCH] Allow lists to contain void elements if not optimizing and not lazy LSO allows this. The compiler does too, but it chokes in RAIL. This affected a test, which has been adjusted too. Untyped lazy list elements can no longer be used in isolation in expression lists (including FOR initializator and iterator). Also rename the terribly named 'self.forbidlabels' to 'self.optenabled' which is more descriptive. --- lslopt/lslparse.py | 10 +++++++--- testparser.py | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lslopt/lslparse.py b/lslopt/lslparse.py index 7459f6a..6a011bb 100644 --- a/lslopt/lslparse.py +++ b/lslopt/lslparse.py @@ -1628,6 +1628,9 @@ list lazy_list_set(list L, integer i, list v) if self.tok[0] not in (']', ')', ';'): while True: expr = self.Parse_expression() + if expr.nt == 'SUBIDX' and expr.t is None: + # Don't accept an untyped lazy list in expression lists + raise EParseTypeMismatch(self) if False is not expected_types is not None: if idx >= len(expected_types): raise EParseFunctionMismatch(self) @@ -1635,7 +1638,8 @@ list lazy_list_set(list L, integer i, list v) expr = self.autocastcheck(expr, expected_types[idx]); except EParseTypeMismatch: raise EParseFunctionMismatch(self) - elif expected_types is False: # don't accept void expressions + elif expected_types is False and self.optenabled: + # don't accept void expressions if optimization is on if expr.t not in types: raise EParseTypeMismatch(self) idx += 1 @@ -1695,7 +1699,7 @@ list lazy_list_set(list L, integer i, list v) return nr(nt=';', t=None) if tok0 == '@': - if not AllowDecl and self.forbidlabels: + if not AllowDecl and self.optenabled: raise EParseInvalidLabelOpt(self) self.NextToken() self.expect('IDENT') @@ -2775,7 +2779,7 @@ list lazy_list_set(list L, integer i, list v) # includes a label as the immediate child of FOR, IF, DO or WHILE. # If optimization is on, such a label will raise an error. That # coding pattern is normally easy to work around anyway. - self.forbidlabels = 'optimize' in options + self.optenabled = 'optimize' in options # Symbol table: # This is a list of all local and global symbol tables. diff --git a/testparser.py b/testparser.py index 9baa974..e9ea5cc 100644 --- a/testparser.py +++ b/testparser.py @@ -128,7 +128,7 @@ class Test02_Parser(UnitTestCase): self.assertRaises(EParseFunctionMismatch, self.parser.parse, '''f(integer i){f(f(1));}''') self.assertRaises(EParseFunctionMismatch, self.parser.parse, '''f(integer i){f();}''') self.assertRaises(EParseDeclarationScope, self.parser.parse, '''f(){if (1) integer i;}''') - self.assertRaises(EParseTypeMismatch, self.parser.parse, '''f(){[f()];}''') + self.assertRaises(EParseTypeMismatch, self.parser.parse, '''f(){[f()];}''', ('optimize',)) self.assertRaises(EParseTypeMismatch, self.parser.parse, '''f(){3.||2;}''') self.assertRaises(EParseTypeMismatch, self.parser.parse, '''f(){3||2.;}''') self.assertRaises(EParseTypeMismatch, self.parser.parse, '''f(){3.|2;}''') @@ -185,6 +185,9 @@ class Test02_Parser(UnitTestCase): self.assertRaises(EParseUndefined, self.parser.parse, '''key a=b;key b;default{timer(){}}''', ['extendedglobalexpr']) + + self.parser.parse('''f(){[f()];}default{timer(){}}''') + # Force a list constant down its throat, to test coverage of LIST_VALUE self.parser.constants['LISTCONST']=[1,2,3] print self.outscript.output(self.parser.parse('default{timer(){LISTCONST;}}'))