Skip to content

Commit 5da9002

Browse files
Update terminology: template -> schema (closes #234)
1 parent f7274b1 commit 5da9002

15 files changed

Lines changed: 310 additions & 313 deletions

File tree

docs/SPECIFICATION.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@
9696

9797
For `INT` and `FLT` types, a declaration MAY name a specific numeric base by writing `TYPE{base} name`, where `base` is an `INT` literal in the range `2` through `64`. A named-base type is a subtype of its parent numeric type: `INT{base}` values are `INT`s and `FLT{base}` values are `FLT`s, but an assignment to a named-base binding requires the value's base to match the declared base. The parent types `INT` and `FLT` (equivalent to `INT{0}` and `FLT{0}`) accept values of any valid numeric base.
9898

99-
For `MAP` types, a declaration MAY specify a template `MAP` by writing `MAP{template} name`, where `template` is any expression that evaluates to a `MAP`. A named-`MAP` type is a subtype of its parent `MAP` type: `MAP{template}` values are `MAP`s, but an assignment to a named-`MAP` binding requires the assigned value to match the template according to the default key-presence rules of the `MATCH` operator. The parent type `MAP` accepts any `MAP` value.
99+
For `MAP` types, a declaration MAY specify a schema `MAP` by writing `MAP{schema} name`, where `schema` is any expression that evaluates to a `MAP`. A named-`MAP` type is a subtype of its parent `MAP` type: `MAP{schema}` values are `MAP`s, but an assignment to a named-`MAP` binding requires the assigned value to match the schema according to the default key-presence rules of the `MATCH` operator. The parent type `MAP` accepts any `MAP` value.
100100

101-
The first assignment to a symbol MUST use a typed form such as `TYPE name = expression`, `TYPE{base} name = expression`, or `MAP{template} name = expression`, with one or more spaces between the type annotation and the name and optional spaces around `=`. Subsequent assignments MAY omit the type annotation, but the symbol's type MUST remain unchanged for the lifetime of that name, including after deletion and re-assignment.
101+
The first assignment to a symbol MUST use a typed form such as `TYPE name = expression`, `TYPE{base} name = expression`, or `MAP{schema} name = expression`, with one or more spaces between the type annotation and the name and optional spaces around `=`. Subsequent assignments MAY omit the type annotation, but the symbol's type MUST remain unchanged for the lifetime of that name, including after deletion and re-assignment.
102102

103103
Assignments to undeclared identifiers without a type annotation MUST raise a runtime error. A binding MUST remain allocated until it is deleted with `DEL("name")`.
104104

@@ -178,7 +178,7 @@
178178
179179
`INT` and `FLT` additionally support named-base variants written `INT{base}` and `FLT{base}`, where `base` is a numeric base in the range `2` through `64` or `0` to denote the parent type. A named-base type and its parent are the same runtime type, but static type checking treats mismatched bases as incompatible. `INT` and `FLT` (base `0`) accept any valid numeric base; `INT{base}` and `FLT{base}` only accept values whose stored base equals the declared base.
180180
181-
`MAP` additionally supports named-template variants written `MAP{template}`, where `template` is any expression that evaluates to a `MAP`. A named-template type and its parent are the same runtime type, but static type checking treats mismatched templates as incompatible. `MAP` accepts any `MAP` value; `MAP{template}` only accepts values whose entries satisfy the template under the default key-presence rules of the `MATCH` operator. Named `MAP` types with different templates are treated as distinct types.
181+
`MAP` additionally supports named-schema variants written `MAP{schema}`, where `schema` is any expression that evaluates to a `MAP`. A named-schema type and its parent are the same runtime type, but static type checking treats mismatched schemas as incompatible. `MAP` accepts any `MAP` value; `MAP{schema}` only accepts values whose entries satisfy the schema under the default key-presence rules of the `MATCH` operator. Named `MAP` types with different schemas are treated as distinct types.
182182
183183
---
184184
@@ -444,7 +444,7 @@
444444
445445
`INT` and `FLT` type annotations MAY include a base specifier written immediately after the type name with no intervening whitespace, in the form `INT{base}` or `FLT{base}`. The `{base}` suffix is part of the type annotation and therefore MUST appear before the required space that separates the type from the declared name. For example, `INT{0d2} value` declares a binary integer, while `FLT{0x} value` declares a hexadecimal float. A base of `0` (typically written as the bare type name) denotes the parent type and accepts any valid numeric base.
446446
447-
`MAP` type annotations MAY include a template specifier written immediately after the type name with no intervening whitespace, in the form `MAP{template}`. The `{template}` suffix is part of the type annotation and therefore MUST appear before the required space that separates the type from the declared name. For example, `MAP{<"x" = 0d1>} value` declares a map that requires an `"x"` key with integer value. The `template` MUST evaluate to a `MAP`. Signatures produced by the `SIGNATURE` built-in MUST include the template in the type annotation for named `MAP` bindings.
447+
`MAP` type annotations MAY include a schema specifier written immediately after the type name with no intervening whitespace, in the form `MAP{schema}`. The `{schema}` suffix is part of the type annotation and therefore MUST appear before the required space that separates the type from the declared name. For example, `MAP{<"x" = 0d1>} value` declares a map that requires an `"x"` key with integer value. The `schema` MUST evaluate to a `MAP`. Signatures produced by the `SIGNATURE` built-in MUST include the schema in the type annotation for named `MAP` bindings.
448448
449449
Reading an undeclared symbol, a declared-but-never-assigned symbol, or a deleted symbol MUST raise a runtime error. Removing a binding MUST preserve its recorded static type, so any later re-assignment to the same name MUST still match the original type.
450450
@@ -841,7 +841,7 @@
841841
842842
- `BOOL KEYIN(INT|FLT|STR key, MAP map)` and `BOOL VALUEIN(ANY value, MAP map)` = MUST return `TRUE` when the given key or value occurs in `map` and `FALSE` otherwise.
843843
844-
- `BOOL MATCH(MAP map, MAP template, INT typing = 0, INT recurse = 0, INT shape = 0)` = MUST return `TRUE` if every key in `template` is present in `map` and, when `typing`, `shape`, or `recurse` is nonzero, the corresponding matched values also satisfy type, shape, and recursive nesting constraints. If `template` contains a key `"match"` whose value is a `MAP`, that entry is metadata and is not itself required in `map`: the effective value of each parameter is the explicit keyword argument if supplied, otherwise the metadata subkey if present and valid, otherwise the implicit default `0`. Each metadata key MUST be an `INT`, and an invalid `"match"` entry, unknown metadata subkey name, or metadata subkey value that is not `INT` MUST cause `MATCH` to return `FALSE` rather than raising an error. A non-`MAP` `"match"` value is matched as an ordinary key.
844+
- `BOOL MATCH(MAP map, MAP schema, INT typing = 0, INT recurse = 0, INT shape = 0)` = MUST return `TRUE` if every key in `schema` is present in `map` and, when `typing`, `shape`, or `recurse` is nonzero, the corresponding matched values also satisfy type, shape, and recursive nesting constraints. If `schema` contains a key `"match"` whose value is a `MAP`, that entry is metadata and is not itself required in `map`: the effective value of each parameter is the explicit keyword argument if supplied, otherwise the metadata subkey if present and valid, otherwise the implicit default `0`. Each metadata key MUST be an `INT`, and an invalid `"match"` entry, unknown metadata subkey name, or metadata subkey value that is not `INT` MUST cause `MATCH` to return `FALSE` rather than raising an error. A non-`MAP` `"match"` value is matched as an ordinary key.
845845
846846
- `MAP INV(MAP map)` = MUST return a new map whose keys and values are reversed. Every value in `map` MUST be a scalar key type (`INT`, `FLT`, or `STR`), and duplicate values MUST raise a runtime error.
847847

src/ast.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ Expr *expr_ident(char *name, int line, int column) {
6161
return expr;
6262
}
6363

64-
Expr *expr_typed_ident(DeclType decl_type, int decl_base, char *name, Expr *template_expr, int line, int column) {
64+
Expr *expr_typed_ident(DeclType decl_type, int decl_base, char *name, Expr *schema_expr, int line, int column) {
6565
Expr *expr = ast_alloc(sizeof(Expr));
6666
expr->type = EXPR_TYPED_IDENT;
6767
expr->line = line;
6868
expr->column = column;
6969
expr->as.typed_ident.decl_type = decl_type;
7070
expr->as.typed_ident.decl_base = decl_base;
7171
expr->as.typed_ident.name = name;
72-
expr->as.typed_ident.template_expr = template_expr;
72+
expr->as.typed_ident.schema_expr = schema_expr;
7373
return expr;
7474
}
7575

@@ -156,7 +156,7 @@ Expr *expr_fmt_str(ExprList parts, int line, int column) {
156156
return expr;
157157
}
158158

159-
Expr *expr_lambda(ParamList params, DeclType return_type, int return_base, Expr *return_template_expr, Stmt *body,
159+
Expr *expr_lambda(ParamList params, DeclType return_type, int return_base, Expr *return_schema_expr, Stmt *body,
160160
int line, int column) {
161161
Expr *expr = ast_alloc(sizeof(Expr));
162162
expr->type = EXPR_LAMBDA;
@@ -165,7 +165,7 @@ Expr *expr_lambda(ParamList params, DeclType return_type, int return_base, Expr
165165
expr->as.lambda.params = params;
166166
expr->as.lambda.return_type = return_type;
167167
expr->as.lambda.return_base = return_base;
168-
expr->as.lambda.return_template_expr = return_template_expr;
168+
expr->as.lambda.return_schema_expr = return_schema_expr;
169169
expr->as.lambda.body = body;
170170
return expr;
171171
}
@@ -236,7 +236,7 @@ Stmt *stmt_expr(Expr *expr, int line, int column) {
236236
}
237237

238238
Stmt *stmt_assign(bool has_type, DeclType decl_type, int decl_base, char *name, Expr *target, Expr *value,
239-
Expr *template_expr, int line, int column) {
239+
Expr *schema_expr, int line, int column) {
240240
Stmt *stmt = ast_alloc(sizeof(Stmt));
241241
stmt->type = STMT_ASSIGN;
242242
stmt->line = line;
@@ -247,19 +247,19 @@ Stmt *stmt_assign(bool has_type, DeclType decl_type, int decl_base, char *name,
247247
stmt->as.assign.name = name;
248248
stmt->as.assign.target = target;
249249
stmt->as.assign.value = value;
250-
stmt->as.assign.template_expr = template_expr;
250+
stmt->as.assign.schema_expr = schema_expr;
251251
return stmt;
252252
}
253253

254-
Stmt *stmt_decl(DeclType decl_type, int decl_base, char *name, Expr *template_expr, int line, int column) {
254+
Stmt *stmt_decl(DeclType decl_type, int decl_base, char *name, Expr *schema_expr, int line, int column) {
255255
Stmt *stmt = ast_alloc(sizeof(Stmt));
256256
stmt->type = STMT_DECL;
257257
stmt->line = line;
258258
stmt->column = column;
259259
stmt->as.decl.decl_type = decl_type;
260260
stmt->as.decl.decl_base = decl_base;
261261
stmt->as.decl.name = name;
262-
stmt->as.decl.template_expr = template_expr;
262+
stmt->as.decl.schema_expr = schema_expr;
263263
return stmt;
264264
}
265265

@@ -305,16 +305,15 @@ Stmt *stmt_parfor(char *counter, Expr *target, Stmt *body, int line, int column)
305305
return stmt;
306306
}
307307

308-
Stmt *stmt_func(char *name, DeclType ret, int return_base, Expr *return_template_expr, Stmt *body, int line,
309-
int column) {
308+
Stmt *stmt_func(char *name, DeclType ret, int return_base, Expr *return_schema_expr, Stmt *body, int line, int column) {
310309
Stmt *stmt = ast_alloc(sizeof(Stmt));
311310
stmt->type = STMT_FUNC;
312311
stmt->line = line;
313312
stmt->column = column;
314313
stmt->as.func_stmt.name = name;
315314
stmt->as.func_stmt.return_type = ret;
316315
stmt->as.func_stmt.return_base = return_base;
317-
stmt->as.func_stmt.return_template_expr = return_template_expr;
316+
stmt->as.func_stmt.return_schema_expr = return_schema_expr;
318317
stmt->as.func_stmt.body = body;
319318
return stmt;
320319
}
@@ -448,7 +447,7 @@ void free_expr(Expr *expr) {
448447
break;
449448
case EXPR_TYPED_IDENT:
450449
free(expr->as.typed_ident.name);
451-
free_expr(expr->as.typed_ident.template_expr);
450+
free_expr(expr->as.typed_ident.schema_expr);
452451
break;
453452
case EXPR_PTR:
454453
free(expr->as.ptr_name);
@@ -472,10 +471,10 @@ void free_expr(Expr *expr) {
472471
for (size_t i = 0; i < expr->as.lambda.params.count; i++) {
473472
free(expr->as.lambda.params.items[i].name);
474473
free_expr(expr->as.lambda.params.items[i].default_value);
475-
free_expr(expr->as.lambda.params.items[i].template_expr);
474+
free_expr(expr->as.lambda.params.items[i].schema_expr);
476475
}
477476
free(expr->as.lambda.params.items);
478-
free_expr(expr->as.lambda.return_template_expr);
477+
free_expr(expr->as.lambda.return_schema_expr);
479478
free_stmt(expr->as.lambda.body);
480479
break;
481480
case EXPR_FMT_STR:
@@ -523,11 +522,11 @@ void free_stmt(Stmt *stmt) {
523522
free_expr(stmt->as.assign.target);
524523
}
525524
free_expr(stmt->as.assign.value);
526-
free_expr(stmt->as.assign.template_expr);
525+
free_expr(stmt->as.assign.schema_expr);
527526
break;
528527
case STMT_DECL:
529528
free(stmt->as.decl.name);
530-
free_expr(stmt->as.decl.template_expr);
529+
free_expr(stmt->as.decl.schema_expr);
531530
break;
532531
case STMT_IF:
533532
free_expr(stmt->as.if_stmt.condition);
@@ -555,10 +554,10 @@ void free_stmt(Stmt *stmt) {
555554
for (size_t i = 0; i < stmt->as.func_stmt.params.count; i++) {
556555
free(stmt->as.func_stmt.params.items[i].name);
557556
free_expr(stmt->as.func_stmt.params.items[i].default_value);
558-
free_expr(stmt->as.func_stmt.params.items[i].template_expr);
557+
free_expr(stmt->as.func_stmt.params.items[i].schema_expr);
559558
}
560559
free(stmt->as.func_stmt.params.items);
561-
free_expr(stmt->as.func_stmt.return_template_expr);
560+
free_expr(stmt->as.func_stmt.return_schema_expr);
562561
free_stmt(stmt->as.func_stmt.body);
563562
break;
564563
case STMT_RETURN:

src/ast.h

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ typedef struct Param {
2424
char *name;
2525
bool coerced;
2626
Expr *default_value; // optional
27-
Expr *template_expr; // NEW: MAP template expression, NULL if none
27+
Expr *schema_expr; // NEW: MAP schema expression, NULL if none
2828
} Param;
2929

3030
typedef struct ParamList {
@@ -79,7 +79,7 @@ struct Expr {
7979
DeclType decl_type;
8080
int decl_base; // 0 = parent INT/FLT, 2..64 = named base
8181
char *name;
82-
Expr *template_expr; // NEW: MAP template expression, NULL if none
82+
Expr *schema_expr; // NEW: MAP schema expression, NULL if none
8383
} typed_ident;
8484
struct {
8585
Expr *callee;
@@ -98,8 +98,8 @@ struct Expr {
9898
struct {
9999
ParamList params;
100100
DeclType return_type;
101-
int return_base; // 0 = parent INT/FLT, 2..64 = named base
102-
Expr *return_template_expr; // NEW: MAP return template, NULL if none
101+
int return_base; // 0 = parent INT/FLT, 2..64 = named base
102+
Expr *return_schema_expr; // NEW: MAP return schema, NULL if none
103103
Stmt *body;
104104
} lambda;
105105
ExprList tns_items;
@@ -164,13 +164,13 @@ struct Stmt {
164164
char *name;
165165
Expr *target;
166166
Expr *value;
167-
Expr *template_expr; // NEW: MAP template expression, NULL if none
167+
Expr *schema_expr; // NEW: MAP schema expression, NULL if none
168168
} assign;
169169
struct {
170170
DeclType decl_type;
171171
int decl_base; // 0 = parent INT/FLT, 2..64 = named base
172172
char *name;
173-
Expr *template_expr; // NEW: MAP template expression, NULL if none
173+
Expr *schema_expr; // NEW: MAP schema expression, NULL if none
174174
} decl;
175175
struct {
176176
Expr *condition;
@@ -197,8 +197,8 @@ struct Stmt {
197197
char *name;
198198
ParamList params;
199199
DeclType return_type;
200-
int return_base; // 0 = parent INT/FLT, 2..64 = named base
201-
Expr *return_template_expr; // NEW: MAP return template, NULL if none
200+
int return_base; // 0 = parent INT/FLT, 2..64 = named base
201+
Expr *return_schema_expr; // NEW: MAP return schema, NULL if none
202202
Stmt *body;
203203
} func_stmt;
204204
struct {
@@ -237,7 +237,7 @@ Expr *expr_flt(double value, int base, int base_is_nan, int line, int column);
237237
Expr *expr_str(char *value, int line, int column);
238238
Expr *expr_ptr(char *name, int line, int column);
239239
Expr *expr_ident(char *name, int line, int column);
240-
Expr *expr_typed_ident(DeclType decl_type, int decl_base, char *name, Expr *template_expr, int line, int column);
240+
Expr *expr_typed_ident(DeclType decl_type, int decl_base, char *name, Expr *schema_expr, int line, int column);
241241
Expr *expr_call(Expr *callee, int line, int column);
242242
void call_kw_add(Expr *call, char *name, Expr *value);
243243
Expr *expr_tns(int line, int column);
@@ -246,7 +246,7 @@ Expr *expr_map(int line, int column);
246246
Expr *expr_index(Expr *target, int line, int column, bool is_map);
247247
Expr *expr_range(Expr *start, Expr *end, int line, int column);
248248
Expr *expr_wildcard(int line, int column);
249-
Expr *expr_lambda(ParamList params, DeclType return_type, int return_base, Expr *return_template_expr, Stmt *body,
249+
Expr *expr_lambda(ParamList params, DeclType return_type, int return_base, Expr *return_schema_expr, Stmt *body,
250250
int line, int column);
251251
Expr *expr_fmt_str(ExprList parts, int line, int column);
252252
void expr_list_add(ExprList *list, Expr *expr);
@@ -255,14 +255,13 @@ Stmt *stmt_block(int line, int column);
255255
Stmt *stmt_async(Stmt *body, int line, int column);
256256
Stmt *stmt_expr(Expr *expr, int line, int column);
257257
Stmt *stmt_assign(bool has_type, DeclType decl_type, int decl_base, char *name, Expr *target, Expr *value,
258-
Expr *template_expr, int line, int column);
259-
Stmt *stmt_decl(DeclType decl_type, int decl_base, char *name, Expr *template_expr, int line, int column);
258+
Expr *schema_expr, int line, int column);
259+
Stmt *stmt_decl(DeclType decl_type, int decl_base, char *name, Expr *schema_expr, int line, int column);
260260
Stmt *stmt_if(Expr *cond, Stmt *then_branch, int line, int column);
261261
Stmt *stmt_while(Expr *cond, Stmt *body, int line, int column);
262262
Stmt *stmt_for(char *counter, Expr *target, Stmt *body, int line, int column);
263263
Stmt *stmt_parfor(char *counter, Expr *target, Stmt *body, int line, int column);
264-
Stmt *stmt_func(char *name, DeclType ret, int return_base, Expr *return_template_expr, Stmt *body, int line,
265-
int column);
264+
Stmt *stmt_func(char *name, DeclType ret, int return_base, Expr *return_schema_expr, Stmt *body, int line, int column);
266265
Stmt *stmt_return(Expr *value, int line, int column);
267266
Stmt *stmt_pop(Expr *expr, int line, int column);
268267
Stmt *stmt_break(Expr *value, int line, int column);

0 commit comments

Comments
 (0)