Skip to content

Commit fbea85c

Browse files
committed
multi dimensional arrays WIP
1 parent 29c0703 commit fbea85c

8 files changed

Lines changed: 110 additions & 32 deletions

File tree

examples/034-array4.pas

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
(*
2+
This file is part of the PascalScript Pascal interpreter.
3+
SPDX-FileCopyrightText: 2026 Christophe 'CHiPs' Petit <chips44@gmail.com>
4+
SPDX-License-Identifier: LGPL-Cols.0-or-later
5+
*)
6+
Program Arrays;
7+
8+
Const
9+
Rows = 3;
10+
Cols = 5;
11+
12+
Type
13+
NumberArray = Array[1..Rows, 1..Cols] Of Integer;
14+
// ArrayOfArray = Array[1..Rows] Of Array[1..Cols] Of Char;
15+
16+
Var
17+
Numbers: NumberArray;
18+
// Chars: ArrayOfArray;
19+
I, J: Integer;
20+
21+
Begin
22+
For I := 1 To Rows Do
23+
For J := 1 To Cols Do
24+
Begin
25+
Numbers[I, J] := (I * J) Mod 26;
26+
// Chars[I, J] := Char(65 + (I * J) Mod 26);
27+
End;
28+
Write(' ');
29+
For J := 1 To Cols Do
30+
Write(J:4);
31+
WriteLn;
32+
For I := 1 To Rows Do
33+
Begin
34+
Write(I:3, ' ');
35+
For J := 1 To Cols Do
36+
Write(Numbers[I, J]:4);
37+
WriteLn;
38+
End;
39+
End.

include/ps_array.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ extern "C"
2727

2828
/** @brief Get array type definition */
2929
ps_type_definition *ps_array_get_type_def(const ps_symbol *array);
30-
/** @brief Get array subrange */
31-
ps_symbol *ps_array_get_subrange(const ps_symbol *array);
30+
/** @brief Get array subranges */
31+
ps_symbol **ps_array_get_subranges(const ps_symbol *array);
32+
/** @brief Get array dimensions */
33+
int ps_array_get_dimensions(const ps_symbol *array_type);
3234
/** @brief Get array item type */
3335
ps_symbol *ps_array_get_item_type(const ps_symbol *array);
3436
/** @brief value := array[index] (allocating value if NULL) */

include/ps_error.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ extern "C"
7676
PS_ERROR_INVALID_PARAMETERS,
7777
PS_ERROR_TOO_MANY_VARIABLES,
7878
PS_ERROR_TOO_MANY_DIMENSIONS,
79+
PS_ERROR_NOT_ENOUGH_DIMENSIONS,
7980
PS_ERROR_PARAMETER_COUNT_MISMATCH,
8081
PS_ERROR_MATH_NAN_INF,
8182
// ...

src/ps_array.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ ps_type_definition *ps_array_get_type_def(const ps_symbol *symbol)
7878
return type_def;
7979
}
8080

81-
ps_symbol *ps_array_get_subrange(const ps_symbol *array_type)
81+
ps_symbol **ps_array_get_subranges(const ps_symbol *array_type)
8282
{
8383
if (ps_array_debug)
8484
ps_symbol_debug(stderr, "ps_array_get_subrange, array_type: ", array_type);
@@ -87,10 +87,18 @@ ps_symbol *ps_array_get_subrange(const ps_symbol *array_type)
8787
ps_type_definition_debug(stderr, "GET_SUBRANGE\tTYPE_DEF\t", type_def);
8888
if (type_def == NULL)
8989
return NULL;
90-
ps_symbol *subrange = type_def->def.a.subranges[0];
90+
ps_symbol **subranges = type_def->def.a.subranges;
91+
return subranges;
92+
}
93+
94+
int ps_array_get_dimensions(const ps_symbol *array_type)
95+
{
9196
if (ps_array_debug)
92-
ps_symbol_debug(stderr, "GET_SUBRANGE\tSUBRANGE\t", subrange);
93-
return subrange;
97+
ps_symbol_debug(stderr, "ps_array_get_dimensions, array_type: ", array_type);
98+
const ps_type_definition *type_def = ps_array_get_type_def(array_type);
99+
if (type_def == NULL)
100+
return NULL;
101+
return type_def->def.a.dimensions;
94102
}
95103

96104
ps_symbol *ps_array_get_item_type(const ps_symbol *array_type)
@@ -125,20 +133,20 @@ ps_error ps_array_get_value(const ps_symbol *array_var, const ps_value *index, p
125133
return error;
126134
}
127135

128-
ps_error ps_array_set_value(ps_symbol *array_var, const ps_value *index, const ps_value *value, bool range_check)
136+
ps_error ps_array_set_value(ps_symbol *array_var, const ps_value **indicies, const ps_value *value, bool range_check)
129137
{
130138
if (ps_array_debug)
131139
{
132140
ps_symbol_debug(stderr, "PS_ARRAY_SET_VALUE, array_var: ", array_var);
133-
ps_value_debug(stderr, "PS_ARRAY_SET_VALUE, index: ", index);
141+
ps_value_debug(stderr, "PS_ARRAY_SET_VALUE, index: ", indicies);
134142
}
135143
if (array_var == NULL || array_var->value == NULL || array_var->value->type == NULL ||
136144
array_var->value->data.a->values == NULL)
137145
return PS_ERROR_INVALID_PARAMETERS;
138146
const ps_symbol *subrange = ps_array_get_subrange(array_var->value->type);
139147
// Get offset from index
140148
ps_array_debug = true;
141-
ps_unsigned offset = ps_type_definition_get_subrange_offset(subrange->value->data.t, index);
149+
ps_unsigned offset = ps_type_definition_get_subrange_offset(subrange->value->data.t, indicies);
142150
if (offset >= array_var->value->data.a->count)
143151
return PS_ERROR_INVALID_SUBRANGE;
144152
ps_array_debug = false;

src/ps_error.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ static const ps_error_message ps_error_messages[] = {
7575
{PS_ERROR_OUT_OF_RANGE, "Out of range"},
7676
{PS_ERROR_INVALID_PARAMETERS, "Invalid parameters"},
7777
{PS_ERROR_TOO_MANY_VARIABLES, "Too many variables in declaration"},
78-
{PS_ERROR_TOO_MANY_DIMENSIONS, "Too many dimensions in array definition"},
78+
{PS_ERROR_TOO_MANY_DIMENSIONS, "Too many dimensions for array"},
79+
{PS_ERROR_NOT_ENOUGH_DIMENSIONS, "Not enough dimensions for array"},
7980
{PS_ERROR_PARAMETER_COUNT_MISMATCH, "Parameter count mismatch"},
8081
{PS_ERROR_MATH_NAN_INF, "Math result is NaN or Infinity"},
8182
{PS_ERROR_MAX, "MAX error?"},

src/ps_value.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@ char *ps_value_to_string(const ps_value *value, bool debug, int16_t width, int16
448448
EXECUTABLE_VALUE
449449
break;
450450
case PS_TYPE_ARRAY:
451-
snprintf(buffer, sizeof(buffer) - 1, "ARRAY[%s] OF %s", value->type->value->data.t->def.a.subranges[0]->name,
452-
value->type->value->data.t->def.a.item_type->name);
451+
snprintf(buffer, sizeof(buffer) - 1, "ARRAY[%s,%d] OF %s", value->type->value->data.t->def.a.subranges[0]->name,
452+
value->type->value->data.t->def.a.dimensions, value->type->value->data.t->def.a.item_type->name);
453453
break;
454454
case PS_TYPE_POINTER:
455455
snprintf(buffer, sizeof(buffer) - 1, "%p", value->data.p);

src/ps_visit_statement.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,34 +80,53 @@ bool ps_visit_compound_statement(ps_interpreter *interpreter, ps_interpreter_mod
8080
VISIT_END("OK")
8181
}
8282

83-
// bool ps_visit_assignment_array(ps_interpreter *interpreter, ps_interpreter_mode mode, ps_symbol *variable)
84-
// {
85-
// VISIT_BEGIN("ASSIGNMENT", "");
86-
// VISIT_END("OK");
87-
// }
88-
8983
bool ps_visit_assignment_array(ps_interpreter *interpreter, ps_interpreter_mode mode, ps_symbol *variable)
9084
{
9185
VISIT_BEGIN("ASSIGNMENT", "ARRAY")
9286

93-
ps_value result = {.type = &ps_system_none, .data.v = NULL};
94-
ps_value index = {.type = &ps_system_none, .data.v = NULL};
87+
ps_value result = {.allocated = false, .type = &ps_system_none, .data.v = NULL};
88+
ps_value indicies[8] = {0};
89+
int dimensions = variable->value->type->value->data.t->def.a.dimensions;
90+
int dimension = 0;
91+
92+
for (ps_unsigned i = 0; i < dimensions; i++)
93+
{
94+
indicies[i].type = variable->value->type->value->data.t->def.a.subranges[i];
95+
indicies[i].allocated = false;
96+
indicies[i].data.v = NULL;
97+
}
9598

9699
EXPECT_TOKEN(PS_TOKEN_LEFT_BRACKET)
97100
READ_NEXT_TOKEN
98-
index.type = variable->value->type->value->data.t->def.a.subranges[0];
99-
if (!ps_visit_expression(interpreter, mode, &index))
100-
TRACE_ERROR("INDEX")
101-
EXPECT_TOKEN(PS_TOKEN_RIGHT_BRACKET)
102-
READ_NEXT_TOKEN
101+
do
102+
{
103+
if (!ps_visit_expression(interpreter, mode, &indicies[dimension]))
104+
TRACE_ERROR("INDEX")
105+
dimension += 1;
106+
if (lexer->current_token.type == PS_TOKEN_COMMA)
107+
{
108+
if (dimension == dimensions)
109+
RETURN_ERROR(PS_ERROR_TOO_MANY_DIMENSIONS)
110+
READ_NEXT_TOKEN
111+
continue;
112+
}
113+
if (lexer->current_token.type == PS_TOKEN_RIGHT_BRACKET)
114+
{
115+
if (dimension != dimensions)
116+
RETURN_ERROR(PS_ERROR_TOO_MANY_DIMENSIONS)
117+
READ_NEXT_TOKEN
118+
break;
119+
}
120+
RETURN_ERROR(PS_ERROR_UNEXPECTED_TOKEN)
121+
} while (true);
103122
EXPECT_TOKEN(PS_TOKEN_ASSIGN)
104123
READ_NEXT_TOKEN
105124
result.type = variable->value->type->value->data.t->def.a.item_type;
106125
if (!ps_visit_expression(interpreter, mode, &result))
107126
TRACE_ERROR("EXPRESSION1")
108127
if (mode == MODE_EXEC)
109128
{
110-
ps_error error = ps_array_set_value(variable, &index, &result, interpreter->range_check);
129+
ps_error error = ps_array_set_value(variable, &indicies, &result, interpreter->range_check);
111130
if (error != PS_ERROR_NONE)
112131
{
113132
interpreter->error = error;

src/ps_visit_type.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ bool ps_visit_type_reference_subrange(ps_interpreter *interpreter, ps_interprete
593593
}
594594

595595
/**
596-
* 'ARRAY' '[' SUBRANGE | IDENTIFIER ']' 'OF' TYPE_REFERENCE
596+
* 'ARRAY' '[' SUBRANGE | IDENTIFIER [ ',' SUBRANGE | IDENTIFIER ]* ']' 'OF' TYPE_REFERENCE
597597
*/
598598
bool ps_visit_type_reference_array(ps_interpreter *interpreter, ps_interpreter_mode mode, ps_symbol **type_symbol,
599599
const char *type_name)
@@ -615,7 +615,7 @@ bool ps_visit_type_reference_array(ps_interpreter *interpreter, ps_interpreter_m
615615
READ_NEXT_TOKEN
616616
do
617617
{
618-
// SUBRANGE (LOW '..' HIGH)
618+
// SUBRANGE: LOW '..' HIGH | IDENTIFIER
619619
if (!ps_visit_type_reference(interpreter, mode, &subrange, NULL))
620620
TRACE_ERROR("DIMENSION")
621621
// Dimension *must* be a subrange
@@ -628,14 +628,17 @@ bool ps_visit_type_reference_array(ps_interpreter *interpreter, ps_interpreter_m
628628
{
629629
if (dimensions == 8)
630630
RETURN_ERROR(PS_ERROR_TOO_MANY_DIMENSIONS)
631+
READ_NEXT_TOKEN
631632
continue;
632633
}
633634
// ']'
634635
if (lexer->current_token.type == PS_TOKEN_RIGHT_BRACKET)
636+
{
637+
READ_NEXT_TOKEN
635638
break;
639+
}
636640
RETURN_ERROR(PS_ERROR_UNEXPECTED_TOKEN)
637641
} while (true);
638-
READ_NEXT_TOKEN
639642
// 'OF'
640643
if (lexer->current_token.type != PS_TOKEN_OF)
641644
RETURN_ERROR(PS_ERROR_UNEXPECTED_TOKEN)
@@ -644,7 +647,11 @@ bool ps_visit_type_reference_array(ps_interpreter *interpreter, ps_interpreter_m
644647
if (!ps_visit_type_reference(interpreter, mode, &item_type, NULL))
645648
TRACE_ERROR("ITEM_TYPE")
646649
// Item type can be any type, even another array
647-
650+
if (item_type->kind != PS_SYMBOL_KIND_TYPE_DEFINITION)
651+
RETURN_ERROR(PS_ERROR_EXPECTED_TYPE)
652+
// For now, item_type cannot be an array type
653+
if (item_type->value->data.t->type == PS_TYPE_ARRAY)
654+
RETURN_ERROR(PS_ERROR_NOT_IMPLEMENTED)
648655
// Create type definition for array
649656
ps_type_definition *type_def = NULL;
650657
ps_identifier name = {0};
@@ -661,11 +668,12 @@ bool ps_visit_type_reference_array(ps_interpreter *interpreter, ps_interpreter_m
661668
ps_type_definition_free(type_def);
662669
RETURN_ERROR(PS_ERROR_OUT_OF_MEMORY);
663670
}
664-
for (int i = 0; i <= dimensions; i++) {
671+
for (int i = 0; i <= dimensions; i++)
672+
{
665673
type_def->def.a.subranges[i] = subranges[i];
666674
}
667-
type_def->def.a.item_type = item_type;
668675
type_def->def.a.dimensions = dimensions;
676+
type_def->def.a.item_type = item_type;
669677
// Register new type definition in symbol table
670678
if (!ps_type_definition_register(interpreter, mode, name, type_def, type_symbol))
671679
RETURN_ERROR(interpreter->error)

0 commit comments

Comments
 (0)