Skip to content

Commit 9fe0e2c

Browse files
gh-12: Add MATCH operator.
1 parent 1152aa2 commit 9fe0e2c

File tree

5 files changed

+64
-4
lines changed

5 files changed

+64
-4
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
## Installation
2-
<code>
3-
Invoke-WebRequest -Uri "https://github.com/python-processing-unit/ASM-Lang/archive/refs/heads/main.zip" -OutFile "path\to\download\ASM-Lang.zip"<br>
2+
<code>Invoke-WebRequest -Uri "https://github.com/python-processing-unit/ASM-Lang/archive/refs/heads/main.zip" -OutFile "path\to\download\ASM-Lang.zip"<br>
43
Expand-Archive -Path "path\to\download\ASM-Lang.zip" -DestinationPath "path\to\extract\ASM-Lang"<br>
54
$old = [Environment]::GetEnvironmentVariable('Path','User')<br>
65
if(-not $old.Split(';') -contains 'path\to\extract\ASM-Lang'){ [Environment]::SetEnvironmentVariable('Path',$old + ';path\to\extract\ASM-Lang','User') }<br>
7-
Remove-Item -Path "path\to\download\ASM-Lang.zip"
8-
</code>
6+
Remove-Item -Path "path\to\download\ASM-Lang.zip"</code>

asm-lang.exe

987 Bytes
Binary file not shown.

docs/SPECIFICATION.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,8 @@
697697
698698
- `VALUEIN(ANY: value, MAP: map):INT` - Returns `1` if any value stored in `map` is equal to `value` using the language's equality semantics, otherwise `0`.
699699
700+
- `MATCH(MAP: map, MAP: template, INT: typing = 0):INT` - Returns `1` if every key in `template` is present in `map`. If `typing` is true, also require that for each matching key the stored value types are identical between `map` and `template`; otherwise return `0`.
701+
700702
- `INV(MAP: map):MAP` - Return a new map whose key/value pairs are reversed. Each value in `map` becomes a key in the returned map and each original key becomes the corresponding value. All values in `map` MUST be scalar (`INT`, `FLT`, or `STR`) so they can be used as keys; otherwise `INV` raises a runtime error. If `map` contains duplicate values (by key type and value), `INV` raises a runtime error.
701703
702704
### 12.8 Concurrency

interpreter.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ def __init__(self) -> None:
534534
self._register_custom("KEYS", 1, 1, self._keys)
535535
self._register_custom("VALUES", 1, 1, self._values)
536536
self._register_custom("KEYIN", 2, 2, self._keyin)
537+
self._register_custom("MATCH", 2, 3, self._match)
537538
self._register_custom("VALUEIN", 2, 2, self._valuein)
538539
self._register_custom("INV", 1, 1, self._inv)
539540
self._register_custom("EXPORT", 2, 2, self._export)
@@ -1260,6 +1261,50 @@ def _valuein(
12601261
return Value(TYPE_INT, 1)
12611262
return Value(TYPE_INT, 0)
12621263

1264+
def _match(
1265+
self,
1266+
interpreter: "Interpreter",
1267+
args: List[Value],
1268+
__: List[Expression],
1269+
___: Environment,
1270+
location: SourceLocation,
1271+
) -> Value:
1272+
# MATCH(MAP: map, MAP: template, INT: typing = 0):INT
1273+
# Return 1 if every key in `template` is present in `map`.
1274+
# If `typing` is true (non-zero), also require the types of the
1275+
# associated values to match between the two maps.
1276+
if len(args) not in (2, 3):
1277+
raise ASMRuntimeError("MATCH requires two or three arguments", location=location, rewrite_rule="MATCH")
1278+
mval = args[0]
1279+
tval = args[1]
1280+
typing_flag = Value(TYPE_INT, 0)
1281+
if len(args) == 3:
1282+
typing_flag = args[2]
1283+
1284+
if mval.type != TYPE_MAP:
1285+
raise ASMRuntimeError("MATCH expects a MAP as first argument", location=location, rewrite_rule="MATCH")
1286+
if tval.type != TYPE_MAP:
1287+
raise ASMRuntimeError("MATCH expects a MAP as second argument", location=location, rewrite_rule="MATCH")
1288+
if typing_flag.type != TYPE_INT:
1289+
raise ASMRuntimeError("MATCH expects typing flag to be INT", location=location, rewrite_rule="MATCH")
1290+
1291+
m = mval.value
1292+
t = tval.value
1293+
assert isinstance(m, Map) and isinstance(t, Map)
1294+
1295+
require_typing = 0 if typing_flag.value == 0 else 1
1296+
1297+
for key in t.data.keys():
1298+
if key not in m.data:
1299+
return Value(TYPE_INT, 0)
1300+
if require_typing:
1301+
mv = m.data[key]
1302+
tv = t.data[key]
1303+
if mv.type != tv.type:
1304+
return Value(TYPE_INT, 0)
1305+
1306+
return Value(TYPE_INT, 1)
1307+
12631308
def _inv(
12641309
self,
12651310
_: "Interpreter",

test.asmln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,21 @@ FUNC BUILTIN_TESTS():INT{
286286
ASSERT( EQ( inv2<10>, "two" ) )
287287
DEL(inv2<1>)
288288
ASSERT( EQ( KEYIN(1, inv2), 0 ) )
289+
# MATCH operator tests
290+
MAP: tmpl1 = < "one" = 1 >
291+
MAP: tmpl2 = < "one" = "x" >
292+
ASSERT( EQ( MATCH(mm2, tmpl1), 1 ) )
293+
ASSERT( EQ( MATCH(mm2, tmpl2), 1 ) )
294+
ASSERT( EQ( MATCH(mm2, tmpl1, 1), 1 ) )
295+
ASSERT( EQ( MATCH(mm2, tmpl2, 1), 0 ) )
296+
MAP: tmpl3 = < "one" = 1, "two" = 10 >
297+
ASSERT( EQ( MATCH(mm2, tmpl3), 1 ) )
298+
MAP: tmpl4 = < "three" = 1 >
299+
ASSERT( EQ( MATCH(mm2, tmpl4), 0 ) )
300+
DEL(tmpl1)
301+
DEL(tmpl2)
302+
DEL(tmpl3)
303+
DEL(tmpl4)
289304
DEL(ks)
290305
DEL(vs)
291306
DEL(inv2)

0 commit comments

Comments
 (0)