Skip to content

Commit f95a3e0

Browse files
committed
Implementing global variable assignment (:=)
1 parent 5606ab4 commit f95a3e0

4 files changed

Lines changed: 94 additions & 149 deletions

File tree

src/Language/Ast.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ data Clause = Clause [Pattern] FunctionBody
145145
data Command = Skip
146146
| Print Expression
147147
| Assign String Expression -- (=)
148+
| GlobalAssign String Expression -- (:=) - global assignment
148149
| AssignIndex String [Expression] Expression -- var[idx..] = expr
149150
| Conditional Expression Command Command -- if-then-else
150151
| Repeat Expression Command -- for 3 do {}

src/Language/Eval.hs

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import Text.Megaparsec (errorBundlePretty, sourcePosPretty, SourcePos)
1515
import Text.Megaparsec.Pos (sourceName, sourceLine, sourceColumn, unPos)
1616
import Data.List (isInfixOf)
1717
import qualified Language.FFI as FFI
18+
import Control.Concurrent.MVar
19+
import System.Mem.StableName
20+
21+
-- Global mutable reference to the global scope using MVar
22+
{-# NOINLINE globalScopeMVar #-}
23+
globalScopeMVar :: MVar (Hashtable String Value)
24+
globalScopeMVar = unsafePerformIO $ do
25+
newMVar emptyHashtable
1826

1927
-- | Error type for better error messages
2028
data EvalError = EvalError
@@ -107,8 +115,69 @@ interpretCommand mpos (Assign name expr) table =
107115
Right v@(Function _) -> return (insertHashtable table name v)
108116
Right v@(Lambda _) -> return (insertHashtable table name v)
109117
Right v@(AlgebraicDataType _ _) -> return (insertHashtable table name v)
110-
Right v@(CBinding _ _) -> return (insertHashtable table name v)
111-
Right v@(NaN) -> return (insertHashtable table name v)
118+
119+
interpretCommand mpos (GlobalAssign name expr) table =
120+
case evaluate expr table of
121+
Right v@(Integer _) -> do
122+
globalScope <- takeMVar globalScopeMVar
123+
let newGlobalScope = insertHashtable globalScope name v
124+
putMVar globalScopeMVar newGlobalScope
125+
return (insertHashtable table name v)
126+
Right v@(Double _) -> do
127+
globalScope <- takeMVar globalScopeMVar
128+
let newGlobalScope = insertHashtable globalScope name v
129+
putMVar globalScopeMVar newGlobalScope
130+
return (insertHashtable table name v)
131+
Right v@(Boolean _) -> do
132+
globalScope <- takeMVar globalScopeMVar
133+
let newGlobalScope = insertHashtable globalScope name v
134+
putMVar globalScopeMVar newGlobalScope
135+
return (insertHashtable table name v)
136+
Right v@(Character _) -> do
137+
globalScope <- takeMVar globalScopeMVar
138+
let newGlobalScope = insertHashtable globalScope name v
139+
putMVar globalScopeMVar newGlobalScope
140+
return (insertHashtable table name v)
141+
Right v@(List _ _) -> do
142+
globalScope <- takeMVar globalScopeMVar
143+
let newGlobalScope = insertHashtable globalScope name v
144+
putMVar globalScopeMVar newGlobalScope
145+
return (insertHashtable table name v)
146+
Right v@(Set _ _) -> do
147+
globalScope <- takeMVar globalScopeMVar
148+
let newGlobalScope = insertHashtable globalScope name v
149+
putMVar globalScopeMVar newGlobalScope
150+
return (insertHashtable table name v)
151+
Right v@(Object _) -> do
152+
globalScope <- takeMVar globalScopeMVar
153+
let newGlobalScope = insertHashtable globalScope name v
154+
putMVar globalScopeMVar newGlobalScope
155+
return (insertHashtable table name v)
156+
Right v@(Function _) -> do
157+
globalScope <- takeMVar globalScopeMVar
158+
let newGlobalScope = insertHashtable globalScope name v
159+
putMVar globalScopeMVar newGlobalScope
160+
return (insertHashtable table name v)
161+
Right v@(Lambda _) -> do
162+
globalScope <- takeMVar globalScopeMVar
163+
let newGlobalScope = insertHashtable globalScope name v
164+
putMVar globalScopeMVar newGlobalScope
165+
return (insertHashtable table name v)
166+
Right v@(AlgebraicDataType _ _) -> do
167+
globalScope <- takeMVar globalScopeMVar
168+
let newGlobalScope = insertHashtable globalScope name v
169+
putMVar globalScopeMVar newGlobalScope
170+
return (insertHashtable table name v)
171+
Right v@(CBinding _ _) -> do
172+
globalScope <- takeMVar globalScopeMVar
173+
let newGlobalScope = insertHashtable globalScope name v
174+
putMVar globalScopeMVar newGlobalScope
175+
return (insertHashtable table name v)
176+
Right v@(NaN) -> do
177+
globalScope <- takeMVar globalScopeMVar
178+
let newGlobalScope = insertHashtable globalScope name v
179+
putMVar globalScopeMVar newGlobalScope
180+
return (insertHashtable table name v)
112181
Right v -> die (mkEvalErrorHint mpos
113182
("cannot assign unexpected value to '" ++ name ++ "'")
114183
("value type: " ++ show v))
@@ -503,10 +572,17 @@ evaluate (Index expr idxExpr) table = do
503572
Nothing -> Left $ mkEvalError Nothing ("key '" ++ [c] ++ "' not found")
504573
_ -> Left $ mkEvalError Nothing ("cannot index " ++ getValueType collection ++ " with " ++ getValueType idx)
505574

506-
evaluate (Variable name) table =
507-
case lookupHashtable table name of
508-
Just val -> Right val
509-
Nothing -> Right Undefined
575+
evaluate (Variable name) table = unsafePerformIO $ do
576+
globalScopeNow <- readMVar globalScopeMVar
577+
case lookupHashtable globalScopeNow name of
578+
Just val -> do
579+
return (Right val)
580+
Nothing ->
581+
case lookupHashtable table name of
582+
Just val -> do
583+
return (Right val)
584+
Nothing -> do
585+
return (Right Undefined)
510586

511587
evaluate (ReadFile filenameExpr) table = do
512588
pathVal <- evaluate filenameExpr table

src/Parsing/Parser.hs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -384,25 +384,30 @@ parseVarWithIndices = do
384384
return (varName, idxs)
385385

386386
parseAssignment :: Parser Command
387-
parseAssignment = try parseIndexedAssign <|> parseSimpleAssign
387+
parseAssignment = try parseIndexedAssign <|> try parseGlobalAssign <|> parseSimpleAssign
388388
where
389389
parseIndexedAssign = try $ do
390390
(varName, idxs) <- lexeme parseVarWithIndices
391391
if null idxs then fail "no indices" else pure ()
392-
-- Allow zero-or-more horizontal whitespace between the variable and '='
393392
_ <- optional scn
394393
_ <- symbol "="
395-
_ <- optional sc -- allow newline before rhs
394+
_ <- optional sc
396395
expr <- parseExpression
397396
return $ AssignIndex varName idxs expr
397+
parseGlobalAssign = do
398+
(varName, idxs) <- lexeme parseVarWithIndices
399+
if not (null idxs) then fail "indexed" else pure ()
400+
_ <- optional scn
401+
_ <- symbol ":="
402+
_ <- optional sc
403+
expr <- parseExpression
404+
return $ GlobalAssign varName expr
398405
parseSimpleAssign = do
399406
(varName, idxs) <- lexeme parseVarWithIndices
400407
if not (null idxs) then fail "indexed" else pure ()
401-
-- Allow zero-or-more horizontal whitespace between the variable and '='
402408
_ <- optional scn
403409
_ <- symbol "="
404-
_ <- optional sc -- allow newline before rhs
405-
-- Check if right-hand side is input() call
410+
_ <- optional sc
406411
inputCall <- optional $ try $ do
407412
_ <- keyword "input"
408413
_ <- symbolNoNl "("

tests/raylib-tests/ball.brn

Lines changed: 0 additions & 137 deletions
This file was deleted.

0 commit comments

Comments
 (0)