Skip to content

Commit 2116c55

Browse files
gh-18: Add lib\diff.asmln
1 parent 17728b1 commit 2116c55

File tree

4 files changed

+88
-2
lines changed

4 files changed

+88
-2
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Ignore Python bytecode cache directories
22
__pycache__/
33
ext/__pycache__/
4+
# Ignore MyPy cache directory
5+
.mypy_cache/

docs/SPECIFICATION.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -775,9 +775,9 @@
775775

776776
### 12.13 File operations:
777777

778-
- `READFILE(STR: path, STR: coding=\"UTF-8\"):STR` — Reads the file at `path` and returns its contents as a `STR`. Supported `coding` values (case-insensitive) are `UTF-8`, `UTF-8 BOM`, `UTF-16 LE`, `UTF-16 BE`, `ANSI` (Windows-1252 on Windows, Latin-1 elsewhere), `binary` (alias `bin`), and `hexadecimal` (alias `hex`). Text codings decode with replacement on invalid bytes; `UTF-8` tolerates and strips a BOM if present. `binary` returns an 8-bit-per-byte bitstring; `hexadecimal` returns a lowercase hexadecimal string. If the file cannot be opened or read, the interpreter raises a runtime error (rewrite: `READFILE`).
778+
- `READFILE(STR: path, STR: coding = "UTF-8"):STR` — Reads the file at `path` and returns its contents as a `STR`. Supported `coding` values (case-insensitive) are `UTF-8`, `UTF-8 BOM`, `UTF-16 LE`, `UTF-16 BE`, `ANSI` (Windows-1252 on Windows, Latin-1 elsewhere), `binary` (alias `bin`), and `hexadecimal` (alias `hex`). Text codings decode with replacement on invalid bytes; `UTF-8` tolerates and strips a BOM if present. `binary` returns an 8-bit-per-byte bitstring; `hexadecimal` returns a lowercase hexadecimal string. If the file cannot be opened or read, the interpreter raises a runtime error (rewrite: `READFILE`).
779779

780-
- `WRITEFILE(STR: blob, STR: path, STR: coding=\"UTF-8\"):INT` — Writes `blob` to `path` using the same `coding` options as `READFILE`. Text codings write in the specified encoding (`UTF-8 BOM` emits a BOM; `ANSI` maps to Windows-1252 on Windows, Latin-1 elsewhere). `binary` expects a bitstring of 0/1 characters whose length is a multiple of 8; `hexadecimal` expects valid hexadecimal. On I/O failure the call returns `INT` 0; invalid coding or malformed binary/hex data raises a runtime error (rewrite: `WRITEFILE`).
780+
- `WRITEFILE(STR: blob, STR: path, STR: coding = "UTF-8"):INT` — Writes `blob` to `path` using the same `coding` options as `READFILE`. Text codings write in the specified encoding (`UTF-8 BOM` emits a BOM; `ANSI` maps to Windows-1252 on Windows, Latin-1 elsewhere). `binary` expects a bitstring of 0/1 characters whose length is a multiple of 8; `hexadecimal` expects valid hexadecimal. On I/O failure the call returns `INT` 0; invalid coding or malformed binary/hex data raises a runtime error (rewrite: `WRITEFILE`).
781781

782782
- `EXISTFILE(STR: path):INT` — Returns `INT` 1 when a filesystem object exists at `path`, otherwise returns `INT` 0. The argument must be a `STR`.
783783

lib/diff.asmln

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# diff utilities for ASM-Lang
2+
#
3+
# API:
4+
# UNIFIED(modified: STR, source: STR):STR
5+
# CONTEXT(modified: STR, source: STR):STR
6+
# SIDE_BY_SIDE(modified: STR, source: STR):STR
7+
8+
FUNC _append_line(STR: acc, STR: line):STR{
9+
IF( EQ(acc, "") ){ RETURN(line) } ELSE { RETURN( JOIN(acc, "\n", line) ) }
10+
}
11+
12+
FUNC UNIFIED(STR: mod, STR: src):STR{
13+
TNS: a = SPLIT(mod, "\n")
14+
TNS: b = SPLIT(src, "\n")
15+
INT: la = TLEN(a, 1)
16+
INT: lb = TLEN(b, 1)
17+
INT: n = MAX(la, lb)
18+
STR: out = ""
19+
INT: i = 1
20+
WHILE( LTE(i, n) ){
21+
STR: left = ""
22+
IF( LTE(i, la) ){ left = a[i] }
23+
STR: right = ""
24+
IF( LTE(i, lb) ){ right = b[i] }
25+
26+
IF( EQ(left, right) ){
27+
IF( NOT(EQ(left, "")) ){
28+
STR: line = JOIN(" ", left)
29+
out = _append_line(out, line)
30+
}
31+
} ELSE {
32+
IF( NOT(EQ(left, "")) ){
33+
out = _append_line(out, JOIN("-", left))
34+
}
35+
IF( NOT(EQ(right, "")) ){
36+
out = _append_line(out, JOIN("+", right))
37+
}
38+
}
39+
i = ADD(i, 1)
40+
}
41+
RETURN(out)
42+
}
43+
44+
FUNC CONTEXT(STR: mod, STR: src):STR{
45+
# For simplicity, use the same output as UNIFIED but with a ' ' prefix
46+
STR: u = UNIFIED(mod, src)
47+
IF( EQ(u, "") ){ RETURN("") }
48+
# Prepend a simple header to resemble context diff
49+
RETURN( JOIN("*** a", "\n", u) )
50+
}
51+
52+
FUNC SIDE_BY_SIDE(STR: mod, STR: src):STR{
53+
TNS: a = SPLIT(mod, "\n")
54+
TNS: b = SPLIT(src, "\n")
55+
INT: la = TLEN(a, 1)
56+
INT: lb = TLEN(b, 1)
57+
INT: n = MAX(la, lb)
58+
STR: out = ""
59+
INT: i = 1
60+
WHILE( LTE(i, n) ){
61+
STR: left = ""
62+
IF( LTE(i, la) ){ left = a[i] }
63+
STR: right = ""
64+
IF( LTE(i, lb) ){ right = b[i] }
65+
STR: marker = " "
66+
IF( NOT(EQ(left, right)) ){ marker = "|" }
67+
STR: line = JOIN(left, " ", marker, " ", right)
68+
out = _append_line(out, line)
69+
i = ADD(i, 1)
70+
}
71+
RETURN(out)
72+
}

test.asmln

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ IMPORT(image)
77
IMPORT(gui)
88
IMPORT(waveforms)
99
IMPORT(stats)
10+
IMPORT(diff)
1011

1112
FUNC BUILTIN_TESTS():INT{
1213
PRINT("Running built-in tests...")
@@ -1119,6 +1120,17 @@ FUNC STDLIB_TESTS():INT{
11191120
} ELSE {
11201121
PRINT("Skipping GUI tests on non-Windows host.")
11211122
}
1123+
1124+
# diff library
1125+
STR: _d_a = "line1\nline2\nline3"
1126+
STR: _d_b = "line1\nlineX\nline3"
1127+
ASSERT( EQ( BOOL(diff.UNIFIED(_d_a, _d_b)), 1 ) )
1128+
ASSERT( EQ( BOOL(diff.CONTEXT(_d_a, _d_b)), 1 ) )
1129+
ASSERT( EQ( BOOL(diff.SIDE_BY_SIDE(_d_a, _d_b)), 1 ) )
1130+
DEL(_d_a)
1131+
DEL(_d_b)
1132+
PRINT("Diff extension tests passed.")
1133+
11221134
PRINT("All standard library tests passed.\n")
11231135
RETURN(0)
11241136
}

0 commit comments

Comments
 (0)