diff --git a/README.md b/README.md index f68a2cc..2d11970 100644 --- a/README.md +++ b/README.md @@ -123,11 +123,13 @@ for i in range(0, 10) { ## While loops +``` a: int = 0; while a < 10 { print(int_to_str(a)+"\n"); a = a + 1; } +``` ## Reading files @@ -136,3 +138,8 @@ while a < 10 { ## Assertions ## Tuples + +``` +a: (int, str) = (0, "hello"); +print(int_to_str(a.0)+" "+a.1+"\n"); +``` \ No newline at end of file diff --git a/TODO.md b/TODO.md index b9908f7..20ad1a9 100644 --- a/TODO.md +++ b/TODO.md @@ -7,7 +7,7 @@ - [x] Make Return just a regular statement - [x] `StructType.{args=...}` syntax - [x] `[:ElementType, elements...]` syntax -- [ ] Tuple element syntax `a.0, a.1`, instead of allowing arbitrary indices into the tuple. This will allow for easier typechecking for tuples +- [x] Tuple element syntax `a.0, a.1`, instead of allowing arbitrary indices into the tuple. This will allow for easier typechecking for tuples - [ ] Make Typechecking a step before anything is interpreted - [ ] Implicit `[elements...]`/`.{args=...}`/`.Member(values...)` syntax - [ ] Destructring of tuples and structs diff --git a/ppp_interpreter.py b/ppp_interpreter.py index d779a55..6b4a225 100644 --- a/ppp_interpreter.py +++ b/ppp_interpreter.py @@ -254,6 +254,11 @@ def calculate_expression(expression: Expression, program: ProgramState) -> Objec case Struct(type, fields): assert field in fields, f"Struct '{type.represent()}' does not have the field '{field}'!" return fields[field] + case TupleObject(type, tuple_): + assert field.isdigit(), field + tuple_index = int(field) + assert 0 <= tuple_index < len(type.types), f"Index {tuple_index} out of bounds for tuple of length {len(type.types)}" + return tuple_[tuple_index] case _: assert False, ("Unimplemented", value, field) case ArrayAccess(array_, index_): array = calculate_expression(array_, program) @@ -264,10 +269,7 @@ def calculate_expression(expression: Expression, program: ProgramState) -> Objec assert 0 <= index.num < len(array.str), f"Index out of bounds. Str of length {len(array.str)} accessed at index {index.num}. {array_, index_}" return Str(array.str[index.num]) elif isinstance(array, TupleObject): - index = calculate_expression(index_, program) - assert isinstance(index, Int), f"Index must be '{IntType.represent()}', got '{index.get_type().represent()}'!" - assert 0 <= index.num <= len(array.tuple), f"Index out of bounds. Tuple of length {len(array.tuple)} accessed at index {index.num}. {array_, index_}" - return array.tuple[index.num] + assert False, f"Cannot use array index for tuple. Use `.` (e.g., `{array_.represent()}.0`) syntax instead" elif isinstance(array, ListObject): array_type = array.type.type index = calculate_expression(index_, program) diff --git a/ppp_parser.py b/ppp_parser.py index 598c359..dd07c94 100644 --- a/ppp_parser.py +++ b/ppp_parser.py @@ -143,6 +143,8 @@ def parse_primary(lexer: Lexer) -> Expression: match next_token.contents: case IdentifierToken(identifier=field): base_expression = FieldAccess(base_expression, field) + case NumberToken(number=number): + base_expression = FieldAccess(base_expression, str(number)) case SymbolToken(symbol=symbol): match symbol: case Symbol.OpenCurly: