Skip to content

Commit dee180d

Browse files
lean: support multilevels for scope variables
fixing mal process output lean: remove SLOW tag
1 parent f736101 commit dee180d

File tree

14 files changed

+389
-271
lines changed

14 files changed

+389
-271
lines changed

IMPLS.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ IMPL:
4949
- {IMPL: julia}
5050
- {IMPL: kotlin}
5151
- {IMPL: latex3, NO_PERF: 1, NO_SELF_HOST: 1, SLOW: 1}
52-
- {IMPL: lean, SLOW: 1}
52+
- {IMPL: lean}
5353
- {IMPL: livescript}
5454
- {IMPL: logo}
5555
- {IMPL: lua}

impls/lean/LeanMal/core.lean

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ mutual
100100
if !(eqInternal a b strict) then false
101101
else eqList nrest vrest strict
102102

103-
-- partial def eqDictKeys (k1: List KeyType) (k2: List KeyType) : Bool :=
104-
-- match k1, k2 with
105-
-- | KeyType.strKey x,
106-
107103
partial def eqDict (n: Dict) (v: Dict) (strict: Bool) : Bool :=
108104
match n, v with
109105
| Dict.empty, Dict.empty => true
@@ -114,7 +110,7 @@ mutual
114110
else
115111
keys1.all (fun k =>
116112
match (d1.get k, d2.get k) with
117-
| (some (_, v1), some (_, v2)) => eqInternal v1 v2 strict
113+
| (some v1, some v2) => eqInternal v1 v2 strict
118114
| _ => false)
119115

120116
partial def eqInternal (first: Types) (second: Types) (strict: Bool) : Bool :=
@@ -136,7 +132,7 @@ mutual
136132
let v := toList vvec
137133
if n.length != v.length then false
138134
else eqList n v strict
139-
| Types.dictVal n, Types.dictVal v => eqDict n v strict
135+
| Types.dictVal n, Types.dictVal v => eqDict n v strict -- mal hash-maps are Dict level 0
140136
| Types.listVal n, Types.vecVal vvec => if strict then false else
141137
let v := toList vvec
142138
if n.length != v.length then false
@@ -181,7 +177,7 @@ def resetAtom (env : Env) (lst: List Types) (args: List Types) : IO (Env × Type
181177
let atomSymbol := args[0]!
182178
match atomSymbol with
183179
| Types.symbolVal sym =>
184-
match env.get (KeyType.strKey sym) with
180+
match env.getRecursive (KeyType.strKey sym) with
185181
| none => throw (IO.userError s!"{sym} not found")
186182
| some (level, _) => match first with
187183
| Types.atomVal x => match x with
@@ -201,8 +197,8 @@ def prStrInternal (lst: List Types) (printReadably: Bool) (sep: String) : String
201197
def KEY_DEBUG_EVAL := "DEBUG-EVAL"
202198

203199
def getDebugEval (env : Env): Bool :=
204-
match env.get (KeyType.strKey KEY_DEBUG_EVAL) with
205-
| some (_, v) => match v with
200+
match env.get (KeyType.strKey KEY_DEBUG_EVAL) 0 with
201+
| some v => match v with
206202
| Types.boolVal v => v
207203
| Types.Nil => false
208204
| _ => false
@@ -236,12 +232,12 @@ def countFunc(env : Env) (lst: List Types) : IO (Env × Types) := do
236232
| Types.Nil => return (env, Types.intVal 0)
237233
| _ => throw (IO.userError "count called on non-sequence")
238234

239-
def readString (lst: List Types) (envir: Env) : IO Types := do
235+
def readString (lst: List Types) : IO Types := do
240236
if lst.length < 1 then throw (IO.userError "read-string: 1 arguments required")
241237
else
242238
let first := lst[0]!
243239
match first with
244-
| Types.strVal v => match read_types_with_env v envir.getDict with -- Dict.empty
240+
| Types.strVal v => match read_types_with_env v with
245241
| Except.error e => throw (IO.userError e)
246242
| Except.ok res => return res
247243
| x => throw (IO.userError s!"unexpected symbol: {x.toString true}, expected: string")
@@ -344,10 +340,10 @@ def makeDictInternal (initialDict : Dict) (lst: List Types) : IO (Dict) := do
344340
| [] => return (acc, acckeys)
345341
| (Types.strVal k) :: v :: rest =>
346342
if acckeys.contains k then return (acc, acckeys)
347-
else loop rest (acckeys ++ [k]) (Dict.insert (KeyType.strKey k) 0 v acc)
343+
else loop rest (acckeys ++ [k]) (Dict.insert (KeyType.strKey k) v acc)
348344
| (Types.keywordVal k) :: v :: rest =>
349345
if acckeys.contains k then return (acc, acckeys)
350-
else loop rest (acckeys ++ [k]) (Dict.insert (KeyType.keywordKey k) 0 v acc)
346+
else loop rest (acckeys ++ [k]) (Dict.insert (KeyType.keywordKey k) v acc)
351347
| _ => throw (IO.userError "Invalid list format: Expected alternating string/keyword and value")
352348
let (v, _) ← loop lst [] initialDict
353349
return v
@@ -406,11 +402,11 @@ def getDict (env : Env) (lst: List Types) : IO (Env × Types) := do
406402
match (rest[0]!) with
407403
| Types.strVal k =>
408404
match v.get (KeyType.strKey k) with
409-
| some (_, val) => return (env, val)
405+
| some val => return (env, val)
410406
| none => return (env, Types.Nil)
411407
| Types.keywordVal k =>
412408
match v.get (KeyType.keywordKey k) with
413-
| some (_, val) => return (env, val)
409+
| some val => return (env, val)
414410
| none => return (env, Types.Nil)
415411
| x => throw (IO.userError s!"unexpected symbol: {x.toString true}, expected: keyword or string")
416412
| Types.Nil => return (env, Types.Nil)
@@ -610,12 +606,8 @@ def setSymbol (env : Env) (name: String) (value: Types): Env :=
610606
-- used to forward mutated atoms and variables defined by `eval` in the root scope
611607
def forwardOuterScopeDefs (envSource: Env) (envOuter: Env): Env :=
612608
envSource.getDict.fold envOuter (fun key l v acc =>
609+
-- do not propagate vars defined in current scope (higher level index)
613610
if l > acc.getLevel then acc
614-
else if l < acc.getLevel then acc.add key l v
615-
else
616-
match acc.get key with
617-
| none => acc.add key l v
618-
| some (lOuter, _) =>
619-
if l != lOuter then acc
620-
else acc.add key l v
611+
-- propagate vars defined in outer scopes - with <= level index (e.g. defined by eval, mutated atoms)
612+
else acc.add key l v
621613
)

impls/lean/LeanMal/reader.lean

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,13 @@ def read_comment : Parsec Unit := do
163163
pure ()
164164

165165
mutual
166-
partial def read_list (envir: Dict := Dict.empty) : Parsec Types := do
166+
partial def read_list : Parsec Types := do
167167
-- ws
168168
let _ ← optional wspace_or_comma_strict
169169
let _ ← pstring "("
170170
let _ ← optional wspace_or_comma_strict
171171
let els ← many (do
172-
let e ← read_types envir
172+
let e ← read_types
173173
let _ ← optional wspace_or_comma_strict
174174
-- let _ ← optional (pchar ',')
175175
return e)
@@ -179,12 +179,12 @@ mutual
179179
let _ ← optional wspace_or_comma_strict
180180
return Types.listVal (els.toList)
181181

182-
partial def read_vector (envir: Dict := Dict.empty) : Parsec Types := do
182+
partial def read_vector : Parsec Types := do
183183
let _ ← optional wspace_or_comma_strict
184184
let _ ← pchar '['
185185
let _ ← optional wspace_or_comma_strict
186186
let els ← many (do
187-
let e ← read_types envir
187+
let e ← read_types
188188
let _ ← optional wspace_or_comma_strict
189189
-- let _ ← optional (pchar ',')
190190
return e)
@@ -195,7 +195,7 @@ mutual
195195
let vec := listToVec vecLst
196196
return Types.vecVal vec
197197

198-
partial def read_hash_map (_: Dict := Dict.empty) : Parsec Types := do
198+
partial def read_hash_map : Parsec Types := do
199199
let _ ← optional wspace_or_comma_strict
200200
let _ ← pchar '{'
201201
let _ ← optional wspace_or_comma_strict
@@ -205,7 +205,7 @@ mutual
205205
let _ ← optional wspace_or_comma_strict
206206
let dict := Array.foldl (fun m (k, v) =>
207207

208-
m.insert k 0 v
208+
m.insert k v
209209
) (Dict.empty) els
210210
return Types.dictVal dict
211211

@@ -222,21 +222,21 @@ mutual
222222
| Types.strVal v => return (KeyType.strKey v, value)
223223
| _ => default
224224

225-
partial def read_symbol (chars: String) (name: String) (envir: Dict := Dict.empty) : Parsec Types := do
225+
partial def read_symbol (chars: String) (name: String) : Parsec Types := do
226226
let _ ← optional wspace_or_comma_strict
227227
let _ ← pstring chars
228-
let elem ← read_types envir
228+
let elem ← read_types
229229
let _ ← optional wspace_or_comma_strict
230230

231231
let vecLst := [(Types.symbolVal name), elem]
232232
return Types.listVal vecLst
233233

234-
partial def read_with_meta (envir: Dict := Dict.empty) : Parsec Types := do
234+
partial def read_with_meta : Parsec Types := do
235235
ws
236236
let _ ← pstring "^"
237237

238238
let els ← many (do
239-
let e ← read_types envir
239+
let e ← read_types
240240
ws
241241
let _ ← optional (pchar ',')
242242
return e)
@@ -245,22 +245,22 @@ mutual
245245
let vecLst := (Types.symbolVal "with-meta") :: elsVec
246246
return Types.listVal (List.append vecLst elsVec)
247247

248-
partial def read_atom (_: Dict := Dict.empty) : Parsec Types :=
248+
partial def read_atom : Parsec Types :=
249249
read_operator_or_number <|> read_float_or_int <|> read_str_val <|> read_keyword <|> read_nil_val <|> read_bool_val <|> read_symbol_val
250250

251-
partial def read_types (envir: Dict := Dict.empty) : Parsec Types := do
251+
partial def read_types : Parsec Types := do
252252
let _ ← optional wspace
253253
let _ ← optional (many read_comment)
254254
match ← peek? with
255255
| none => fail "endofinput"
256256
| some _ =>
257-
read_list envir <|> read_vector envir <|> read_hash_map envir <|> read_symbol "'" "quote" envir <|> read_symbol "`" "quasiquote" envir <|> read_symbol "~@" "splice-unquote" envir <|> read_symbol "~" "unquote" envir <|> read_symbol "@" "deref" envir <|> read_with_meta envir <|> read_atom envir
257+
read_list <|> read_vector <|> read_hash_map <|> read_symbol "'" "quote" <|> read_symbol "`" "quasiquote" <|> read_symbol "~@" "splice-unquote" <|> read_symbol "~" "unquote" <|> read_symbol "@" "deref" <|> read_with_meta <|> read_atom
258258
end
259259

260-
def read_types_with_env (input : String) (envir: Dict := Dict.empty) : Except String Types :=
261-
match read_types envir input.trim.iter with
260+
def read_types_with_env (input : String) : Except String Types :=
261+
match read_types input.trim.iter with
262262
| Lean.Parsec.ParseResult.success _ res => Except.ok res
263263
| Lean.Parsec.ParseResult.error _ err => Except.error err
264264

265265
def read_str (input : String) : Except String Types :=
266-
read_types_with_env input (Dict.empty : Dict.{u})
266+
read_types_with_env input

impls/lean/LeanMal/step1_read_print.lean

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import LeanMal.printer
44
universe u
55

66
def READ (input : String) :=
7-
read_str.{u} input
7+
read_str input
88

99
def EVAL (ast : Types) (_: String) := ast
1010

1111
def PRINT (ast : Types): String :=
1212
pr_str true ast
1313

1414
def rep (input : String): String :=
15-
match READ.{u} input with
15+
match READ input with
1616
| Except.ok result =>
1717
PRINT (EVAL result "")
1818
| Except.error err =>
@@ -31,4 +31,4 @@ def main : IO Unit := do
3131
if value.isEmpty then
3232
donext := false
3333
else
34-
IO.println (rep.{u} value)
34+
IO.println (rep value)

impls/lean/LeanMal/step2_eval.lean

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import LeanMal.printer
44
universe u
55

66
def READ (input : String): Except String Types :=
7-
read_str.{u} input
7+
read_str input
88

99
def sum (env : Env) (lst: List Types) : IO (Env × Types) := do
1010
match lst with
@@ -54,7 +54,7 @@ mutual
5454

5555
partial def evalTypes (env : Env) (ast : Types) : IO (Env × Types) := do
5656
match ast with
57-
| Types.symbolVal v => match env.get (KeyType.strKey v) with
57+
| Types.symbolVal v => match env.getRecursive (KeyType.strKey v) with
5858
| some (_, vi) => return (env, vi)
5959
| none => return (env, Types.symbolVal v )
6060
| Types.listVal el => (evalList env el)
@@ -77,8 +77,8 @@ mutual
7777
let keys: List String := match params with
7878
| Types.listVal v => v.map fun x => x.toString false
7979
| _ => []
80-
let argsDict := (buildDict 0 keys results)
81-
let merged := (newEnv.merge fenv).mergeDict (fenv.getLevel + 1) argsDict
80+
let argsEnv := (buildEnv (fenv.getLevel + 1) keys results)
81+
let merged := (newEnv.merge fenv).merge argsEnv
8282
evalTypes merged body
8383
| Fun.macroFn _ _ _ => throw (IO.userError "macro not implemented")
8484
| _ => throw (IO.userError s!"`unexpected token, expected: function`")
@@ -103,10 +103,10 @@ mutual
103103
partial def evalDictInner (env: Env) (lst : Dict) : IO (Env × Dict) := do
104104
match lst with
105105
| Dict.empty => return (env, lst)
106-
| Dict.insert k _ v restDict =>
106+
| Dict.insert k v restDict =>
107107
let (newEnv, newVal) ← evalTypes env v
108108
let (updatedEnv, updatedDict) ← evalDictInner newEnv restDict
109-
let newDict := Dict.insert k 0 newVal updatedDict
109+
let newDict := Dict.insert k newVal updatedDict
110110
return (updatedEnv, newDict)
111111

112112
partial def evalFuncArgs (env: Env) (args: List Types) : IO (Env × List Types) := do
@@ -121,10 +121,10 @@ def PRINT (ast : Types): String :=
121121
pr_str true ast
122122

123123
def rep (input : String): IO String := do
124-
match READ.{u} input with
124+
match READ input with
125125
| Except.ok result =>
126126
try
127-
let (_, res) ← evalTypes (Env.data 0 Dict.empty) result
127+
let (_, res) ← evalTypes (Env.data 0 LevelDict.empty KLDict.empty) result
128128
return PRINT res
129129
catch
130130
| e => return s!"Error: {e}"
@@ -144,5 +144,5 @@ def main : IO Unit := do
144144
if value.isEmpty then
145145
donext := false
146146
else
147-
let output ← rep.{u} value
147+
let output ← rep value
148148
IO.println output

impls/lean/LeanMal/step3_env.lean

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import LeanMal.types
55
universe u
66

77
def READ (input : String): Except String Types :=
8-
read_str.{u} input
8+
read_str input
99

1010
def sum (env : Env) (lst: List Types) : IO (Env × Types) := do
1111
match lst with
@@ -55,7 +55,7 @@ mutual
5555

5656
partial def evalTypes (env : Env) (ast : Types) : IO (Env × Types) := do
5757
match ast with
58-
| Types.symbolVal v => match env.get (KeyType.strKey v) with
58+
| Types.symbolVal v => match env.getRecursive (KeyType.strKey v) with
5959
| some (_, vi) => return (env, vi)
6060
| none => throw (IO.userError s!"'{v}' not found")
6161
| Types.listVal el => (evalList env el)
@@ -78,8 +78,8 @@ mutual
7878
| Types.listVal v => v.map fun x => x.toString false
7979
| _ => []
8080
let argsLevel := fenv.getLevel + 1
81-
let argsDict := (buildDict argsLevel keys results)
82-
let merged := (newEnv.merge fenv).mergeDict argsLevel argsDict
81+
let argsEnv := (buildEnv argsLevel keys results)
82+
let merged := (newEnv.merge fenv).merge argsEnv
8383
evalTypes merged body
8484
| Fun.macroFn _ _ _ => throw (IO.userError "macro not implemented")
8585
| _ => throw (IO.userError s!"`unexpected token, expected: function`")
@@ -106,10 +106,10 @@ mutual
106106
partial def evalDictInner (env: Env) (lst : Dict) : IO (Env × Dict) := do
107107
match lst with
108108
| Dict.empty => return (env, lst)
109-
| Dict.insert k _ v restDict =>
109+
| Dict.insert k v restDict =>
110110
let (newEnv, newVal) ← evalTypes env v
111111
let (updatedEnv, updatedDict) ← evalDictInner newEnv restDict
112-
let newDict := Dict.insert k 0 newVal updatedDict
112+
let newDict := Dict.insert k newVal updatedDict
113113
return (updatedEnv, newDict)
114114

115115
partial def evalFuncArgs (env: Env) (args: List Types) : IO (Env × List Types) := do
@@ -173,7 +173,7 @@ def PRINT (ast : Types): String :=
173173
pr_str true ast
174174

175175
def rep (env: Env) (input : String): IO (Env × String) := do
176-
match READ.{u} input with
176+
match READ input with
177177
| Except.ok result =>
178178
try
179179
let (newenv, res) ← evalTypes env result
@@ -188,7 +188,7 @@ def repAndPrint (env: Env) (output : String): IO Env := do
188188
return env
189189

190190
def main : IO Unit := do
191-
let mut env := loadFnNativeAll (Env.data 0 Dict.empty)
191+
let mut env := loadFnNativeAll (Env.data 0 LevelDict.empty KLDict.empty)
192192
let mut donext := true
193193
while donext do
194194
IO.print "user> "
@@ -201,5 +201,5 @@ def main : IO Unit := do
201201
if value.isEmpty then
202202
donext := false
203203
else
204-
let (newenv, value) ← rep.{u} env value
204+
let (newenv, value) ← rep env value
205205
env ← repAndPrint newenv value

0 commit comments

Comments
 (0)