Skip to content

Commit

Permalink
powershell: merge eval-ast and fix a few tests
Browse files Browse the repository at this point in the history
Fix (false? 1) and (true? 0).
Change the type of the env.{find,get,set} key to a raw string.
Merge eval-ast into EVAL.
Implement DEBUG-EVAL.
Prevent defmacro! from mutating the original function.
  • Loading branch information
asarhaddon committed Aug 26, 2024
1 parent dd14d8e commit 13a38f0
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 260 deletions.
4 changes: 2 additions & 2 deletions impls/powershell/core.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ $core_ns = @{
"throw" = Get-Command mal_throw;

"nil?" = { param($a); $a -eq $null };
"true?" = { param($a); $a -eq $true };
"false?" = { param($a); $a -eq $false };
"true?" = { param($a); $a -is [Boolean] -and $a -eq $true };
"false?" = { param($a); $a -is [Boolean] -and $a -eq $false };
"number?" = { param($a); $a -is [int32] };
"string?" = { param($a); string? $a };
"symbol" = Get-Command new-symbol;
Expand Down
8 changes: 4 additions & 4 deletions impls/powershell/env.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ Class Env {
}

[Object] set($key, $value) {
$this.data[$key.value] = $value
$this.data[$key] = $value
return $value
}

[Env] find($key) {
if ($this.data.Contains($key.value)) {
if ($this.data.Contains($key)) {
return $this
} elseif ($this.outer -ne $null) {
return $this.outer.find($key)
Expand All @@ -44,9 +44,9 @@ Class Env {
[Object] get($key) {
$e = $this.find($key)
if ($e -ne $null) {
return $e.data[$key.value]
return $e.data[$key]
} else {
throw "'$($key.value)' not found"
throw "'$($key)' not found"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion impls/powershell/run
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/bin/bash
#!/bin/sh
exec powershell $(dirname $0)/${STEP:-stepA_mal}.ps1 "${@}"
17 changes: 6 additions & 11 deletions impls/powershell/step2_eval.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ function READ([String] $str) {
}

# EVAL
function eval_ast($ast, $env) {
function EVAL($ast, $env) {
# Write-Host "EVAL: $(pr_str $ast)"

if ($ast -eq $null) { return $ast }
switch ($ast.GetType().Name) {
"Symbol" { return $env[$ast.value] }
"List" { return new-list @($ast.values | ForEach-Object { EVAL $_ $env }) }
"List" { } # continue after the switch
"Vector" { return new-vector @($ast.values | ForEach-Object { EVAL $_ $env }) }
"HashMap" {
$hm = new-hashmap @()
Expand All @@ -25,18 +27,11 @@ function eval_ast($ast, $env) {
}
default { return $ast }
}
}

function EVAL($ast, $env) {
# Write-Host "EVAL: $(pr_str $ast)"
if ($ast -eq $null) { return $ast }
if (-not (list? $ast)) {
return (eval_ast $ast $env)
}
if (empty? $ast) { return $ast }

$el = (eval_ast $ast $env)
$f, $fargs = $el.first(), $el.rest().values
$f = ( EVAL $ast.first() $env )
$fargs = @($ast.rest().values | ForEach-Object { EVAL $_ $env })
return &$f @fargs
}

Expand Down
39 changes: 21 additions & 18 deletions impls/powershell/step3_env.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,21 @@ function READ([String] $str) {
}

# EVAL
function eval_ast($ast, $env) {
function EVAL($ast, $env) {

$dbgeval_env = ($env.find("DEBUG-EVAL"))
if ($dbgeval_env -ne $null) {
$dbgeval = $dbgeval_env.get("DEBUG-EVAL")
if ($dbgeval -ne $null -and
-not ($dbgeval -is [Boolean] -and $dbgeval -eq $false)) {
Write-Host "EVAL: $(pr_str $ast)"
}
}

if ($ast -eq $null) { return $ast }
switch ($ast.GetType().Name) {
"Symbol" { return $env.get($ast) }
"List" { return new-list @($ast.values | ForEach-Object { EVAL $_ $env }) }
"Symbol" { return $env.get($ast.value) }
"List" { } # continue after the switch
"Vector" { return new-vector @($ast.values | ForEach-Object { EVAL $_ $env }) }
"HashMap" {
$hm = new-hashmap @()
Expand All @@ -26,31 +36,24 @@ function eval_ast($ast, $env) {
}
default { return $ast }
}
}

function EVAL($ast, $env) {
# Write-Host "EVAL: $(pr_str $ast)"
if ($ast -eq $null) { return $ast }
if (-not (list? $ast)) {
return (eval_ast $ast $env)
}
if (empty? $ast) { return $ast }

$a0, $a1, $a2 = $ast.nth(0), $ast.nth(1), $ast.nth(2)
switch -casesensitive ($a0.value) {
"def!" {
return $env.set($a1, (EVAL $a2 $env))
return $env.set($a1.value, (EVAL $a2 $env))
}
"let*" {
$let_env = new-env $env
for ($i=0; $i -lt $a1.values.Count; $i+=2) {
$_ = $let_env.set($a1.nth($i), (EVAL $a1.nth(($i+1)) $let_env))
$_ = $let_env.set($a1.nth($i).value, (EVAL $a1.nth(($i+1)) $let_env))
}
return EVAL $a2 $let_env
}
default {
$el = (eval_ast $ast $env)
$f, $fargs = $el.first(), $el.rest().values
$f = ( EVAL $ast.first() $env )
$fargs = @($ast.rest().values | ForEach-Object { EVAL $_ $env })
return &$f @fargs
}
}
Expand All @@ -63,10 +66,10 @@ function PRINT($exp) {

# REPL
$repl_env = new-env
$_ = $repl_env.set((new-symbol "+"), { param($a, $b); $a + $b })
$_ = $repl_env.set((new-symbol "-"), { param($a, $b); $a - $b })
$_ = $repl_env.set((new-symbol "*"), { param($a, $b); $a * $b })
$_ = $repl_env.set((new-symbol "/"), { param($a, $b); $a / $b })
$_ = $repl_env.set("+", { param($a, $b); $a + $b })
$_ = $repl_env.set("-", { param($a, $b); $a - $b })
$_ = $repl_env.set("*", { param($a, $b); $a * $b })
$_ = $repl_env.set("/", { param($a, $b); $a / $b })

function REP([String] $str) {
return PRINT (EVAL (READ $str) $repl_env)
Expand Down
38 changes: 22 additions & 16 deletions impls/powershell/step4_if_fn_do.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ function READ([String] $str) {
}

# EVAL
function eval_ast($ast, $env) {
function EVAL($ast, $env) {

$dbgeval_env = ($env.find("DEBUG-EVAL"))
if ($dbgeval_env -ne $null) {
$dbgeval = $dbgeval_env.get("DEBUG-EVAL")
if ($dbgeval -ne $null -and
-not ($dbgeval -is [Boolean] -and $dbgeval -eq $false)) {
Write-Host "EVAL: $(pr_str $ast)"
}
}

if ($ast -eq $null) { return $ast }
switch ($ast.GetType().Name) {
"Symbol" { return $env.get($ast) }
"List" { return new-list @($ast.values | ForEach-Object { EVAL $_ $env }) }
"Symbol" { return $env.get($ast.value) }
"List" { } # continue after the switch
"Vector" { return new-vector @($ast.values | ForEach-Object { EVAL $_ $env }) }
"HashMap" {
$hm = new-hashmap @()
Expand All @@ -27,30 +37,26 @@ function eval_ast($ast, $env) {
}
default { return $ast }
}
}

function EVAL($ast, $env) {
# Write-Host "EVAL: $(pr_str $ast)"
if ($ast -eq $null) { return $ast }
if (-not (list? $ast)) {
return (eval_ast $ast $env)
}
if (empty? $ast) { return $ast }

$a0, $a1, $a2 = $ast.nth(0), $ast.nth(1), $ast.nth(2)
switch -casesensitive ($a0.value) {
"def!" {
return $env.set($a1, (EVAL $a2 $env))
return $env.set($a1.value, (EVAL $a2 $env))
}
"let*" {
$let_env = new-env $env
for ($i=0; $i -lt $a1.values.Count; $i+=2) {
$_ = $let_env.set($a1.nth($i), (EVAL $a1.nth(($i+1)) $let_env))
$_ = $let_env.set($a1.nth($i).value, (EVAL $a1.nth(($i+1)) $let_env))
}
return EVAL $a2 $let_env
}
"do" {
return (eval_ast $ast.rest() $env).last()
for ($i=1; $i -lt ($ast.values.Count - 1); $i+=1) {
$_ = (EVAL $ast.values[$i] $env)
}
return (EVAL $ast.values[$i] $env)
}
"if" {
$cond = (EVAL $a1 $env)
Expand All @@ -69,8 +75,8 @@ function EVAL($ast, $env) {
}.GetNewClosure()
}
default {
$el = (eval_ast $ast $env)
$f, $fargs = $el.first(), $el.rest().values
$f = ( EVAL $ast.first() $env )
$fargs = @($ast.rest().values | ForEach-Object { EVAL $_ $env })
return &$f @fargs
}
}
Expand All @@ -90,7 +96,7 @@ function REP([String] $str) {

# core.EXT: defined using PowerShell
foreach ($kv in $core_ns.GetEnumerator()) {
$_ = $repl_env.set((new-symbol $kv.Key), $kv.Value)
$_ = $repl_env.set($kv.Key, $kv.Value)
}

# core.mal: defined using the language itself
Expand Down
43 changes: 23 additions & 20 deletions impls/powershell/step5_tco.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,23 @@ function READ([String] $str) {
}

# EVAL
function eval_ast($ast, $env) {
function EVAL($ast, $env) {

while ($true) {

$dbgeval_env = ($env.find("DEBUG-EVAL"))
if ($dbgeval_env -ne $null) {
$dbgeval = $dbgeval_env.get("DEBUG-EVAL")
if ($dbgeval -ne $null -and
-not ($dbgeval -is [Boolean] -and $dbgeval -eq $false)) {
Write-Host "EVAL: $(pr_str $ast)"
}
}

if ($ast -eq $null) { return $ast }
switch ($ast.GetType().Name) {
"Symbol" { return $env.get($ast) }
"List" { return new-list @($ast.values | ForEach-Object { EVAL $_ $env }) }
"Symbol" { return $env.get($ast.value) }
"List" { } # continue after the switch
"Vector" { return new-vector @($ast.values | ForEach-Object { EVAL $_ $env }) }
"HashMap" {
$hm = new-hashmap @()
Expand All @@ -27,36 +39,27 @@ function eval_ast($ast, $env) {
}
default { return $ast }
}
}

function EVAL($ast, $env) {
while ($true) {
# Write-Host "EVAL: $(pr_str $ast)"
if ($ast -eq $null) { return $ast }
if (-not (list? $ast)) {
return (eval_ast $ast $env)
}
if (empty? $ast) { return $ast }

$a0, $a1, $a2 = $ast.nth(0), $ast.nth(1), $ast.nth(2)
switch -casesensitive ($a0.value) {
"def!" {
return $env.set($a1, (EVAL $a2 $env))
return $env.set($a1.value, (EVAL $a2 $env))
}
"let*" {
$let_env = new-env $env
for ($i=0; $i -lt $a1.values.Count; $i+=2) {
$_ = $let_env.set($a1.nth($i), (EVAL $a1.nth(($i+1)) $let_env))
$_ = $let_env.set($a1.nth($i).value, (EVAL $a1.nth(($i+1)) $let_env))
}
$env = $let_env
$ast = $a2 # TCO
}
"do" {
if ($ast.values.Count -gt 2) {
$middle = new-list $ast.values[1..($ast.values.Count-2)]
$_ = eval_ast $middle $env
for ($i=1; $i -lt ($ast.values.Count - 1); $i+=1) {
$_ = (EVAL $ast.values[$i] $env)
}
$ast = $ast.last() # TCO
$ast = $ast.values[$i] # TCO
}
"if" {
$cond = (EVAL $a1 $env)
Expand All @@ -76,8 +79,8 @@ function EVAL($ast, $env) {
return new-malfunc $a2 $a1.values $env $fn
}
default {
$el = (eval_ast $ast $env)
$f, $fargs = $el.first(), $el.rest().values
$f = ( EVAL $ast.first() $env )
$fargs = @($ast.rest().values | ForEach-Object { EVAL $_ $env })
if (malfunc? $f) {
$env = (new-env $f.env $f.params $fargs)
$ast = $f.ast # TCO
Expand All @@ -103,7 +106,7 @@ function REP([String] $str) {

# core.EXT: defined using PowerShell
foreach ($kv in $core_ns.GetEnumerator()) {
$_ = $repl_env.set((new-symbol $kv.Key), $kv.Value)
$_ = $repl_env.set($kv.Key, $kv.Value)
}

# core.mal: defined using the language itself
Expand Down
Loading

0 comments on commit 13a38f0

Please sign in to comment.