Skip to content

Commit 5f6f845

Browse files
committed
Fixes to function nesting, casts, etc.
1 parent d040c09 commit 5f6f845

File tree

7 files changed

+117
-31
lines changed

7 files changed

+117
-31
lines changed

examples/raylib.in

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
external "__default" = do
2+
sin :: Double -> Double
3+
end
4+
5+
external "libraylib" = do
6+
InitWindow :: Int -> Int -> String -> IO
7+
BeginDrawing :: IO
8+
ClearBackground :: Int -> IO
9+
DrawText :: String -> Int -> Int -> Int -> Int -> IO
10+
EndDrawing :: IO
11+
CloseWindow :: IO
12+
WindowShouldClose :: Int
13+
SetTargetFPS :: Int -> IO
14+
GetFrameTime :: Float
15+
DrawTriangle :: Vector2 -> Vector2 -> Vector2 -> Int -> IO
16+
DrawRectangle :: Int -> Int -> Int -> Int -> Int -> IO
17+
DrawPixel :: Int -> Int -> Int -> IO
18+
DrawLine :: Int -> Int -> Int -> Int -> Int -> IO
19+
end
20+
21+
let gray = 0xFF888888
22+
let violet = 0xFF8800FF
23+
let screenWidth = 800
24+
let screenHeight = 450
25+
26+
let loop (tick: Int) = do
27+
BeginDrawing
28+
ClearBackground 0
29+
DrawText "Hello Indigo", 100, 100, 100, violet
30+
EndDrawing
31+
if WindowShouldClose == 0 then do
32+
loop (tick + 1)
33+
else do
34+
end
35+
end
36+
let main = do
37+
InitWindow screenWidth, screenHeight, "Hello Indigo"
38+
SetTargetFPS 60
39+
loop 0
40+
CloseWindow
41+
end

lib/AST.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ typeOf (Struct _ _) = error "Cannot infer type of struct"
224224
typeOf (StructLit x _) = StructT x
225225
typeOf (ListLit x) = if null x then List Any else List $ typeOf $ head x
226226
typeOf (ArrayAccess _ _) = error "Cannot infer type of array access"
227-
typeOf (Modulo _ _) = error "Cannot infer type of modulo"
227+
typeOf (Modulo x _) = typeOf x
228228
typeOf (Target _ _) = error "Cannot infer type of target"
229229
typeOf (ListConcat{}) = List Any
230230
typeOf (ListPattern _) = List Any

lib/BytecodeCompiler.hs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import Control.Monad (when, (>=>))
77
import Control.Monad.Loops (firstM)
88
import Control.Monad.State (MonadIO (liftIO), StateT, gets, modify)
99
import Data.Functor ((<&>))
10-
import Data.List (elemIndex, find, intercalate, isInfixOf)
10+
import Data.List (elemIndex, find, inits, intercalate, isInfixOf, tails)
11+
import Data.List.Split qualified
1112
import Data.Maybe (fromJust, isJust, isNothing)
1213
import Data.Text (isPrefixOf, splitOn)
1314
import Data.Text qualified
@@ -228,7 +229,11 @@ compileExpr (Parser.FuncCall funcName args _) = do
228229
funcDecs' <- gets funcDecs
229230
curCon <- gets currentContext
230231
externals' <- gets externals
231-
let fun = case findFunction (curCon ++ "@" ++ funcName) functions' argTypes of
232+
let contexts = map (T.pack . intercalate "@") (inits (Data.List.Split.splitOn "@" curCon))
233+
-- Find the function in any context using firstM
234+
let contextFunctions = firstJust (\context -> findFunction (Data.Text.unpack context ++ "@" ++ funcName) functions' argTypes) contexts
235+
236+
let fun = case contextFunctions of
232237
(Just lf) -> lf
233238
Nothing -> case findFunction funcName functions' argTypes of
234239
(Just f) -> f
@@ -358,15 +363,17 @@ compileExpr (Parser.If ifCond ifThen ifElse) = do
358363
return $ cond' ++ [Jf elseLabel] ++ then' ++ [Jmp endLabel, Label elseLabel] ++ else' ++ [Label endLabel]
359364
compileExpr (Parser.FloatLit x) = return [Push (DFloat x)]
360365
compileExpr (Parser.BoolLit x) = return [Push (DBool x)]
361-
compileExpr (Parser.TypeLit x) = case x of
362-
Parser.Int -> return [Push $ DInt 0]
363-
Parser.Float -> return [Push $ DFloat 0.0]
364-
Parser.String -> return [Push $ DString ""]
365-
Parser.Bool -> return [Push $ DBool False]
366-
Parser.CPtr -> return [Push $ DCPtr $ ptrToWordPtr nullPtr]
367-
Parser.Double -> return [Push $ DDouble 0.0]
368-
_ -> error $ "Type " ++ show x ++ " is not implemented"
369-
compileExpr (Parser.Cast from to) = compileExpr from >>= \x -> compileExpr to >>= \y -> return (x ++ y ++ [Cast])
366+
compileExpr (Parser.Cast from to) = do
367+
from' <- compileExpr from
368+
let to' = compileType to
369+
return $ from' ++ to' ++ [Cast]
370+
where
371+
compileType :: Parser.Expr -> [Instruction]
372+
compileType (Parser.Var "Int" _) = [Push $ DInt 0]
373+
compileType (Parser.Var "Float" _) = [Push $ DFloat 0.0]
374+
compileType (Parser.Var "Double" _) = [Push $ DDouble 0.0]
375+
compileType (Parser.Var "CPtr" _) = [Push $ DCPtr $ ptrToWordPtr nullPtr]
376+
compileType x = error $ "Type " ++ show x ++ " is not implemented"
370377
compileExpr st@(Parser.Struct _ fields) = do
371378
modify (\s -> s{structDecs = st : structDecs s})
372379
mapM_ createFieldTrait fields
@@ -420,14 +427,14 @@ compileExpr (Parser.Impl name for methods) = do
420427
compileExpr (Parser.Lambda args body) = do
421428
fId <- allocId
422429
curCon <- gets currentContext
423-
lets' <- gets functions
424430
let name = "__lambda" ++ show fId
425-
let letsOfCurrentContext = filter (\x -> x.context == curCon && not ("__" `isInfixOf` x.baseName)) lets'
426-
let argsAndLets = args ++ map (\x -> Parser.Var (drop 1 (dropWhile (/= '@') x.baseName)) zeroPosition) letsOfCurrentContext
427-
let ldec = Parser.FuncDec name (replicate (length args + 1) Parser.Any)
428-
let ldef = Parser.FuncDef name argsAndLets body
429-
mapM_ compileExpr [ldec, ldef]
430-
return $ map (\x -> Call x.funame) letsOfCurrentContext ++ [PushPf (curCon ++ "@" ++ name) (length letsOfCurrentContext)]
431+
let def = Parser.FuncDef name args body
432+
let dec = Parser.FuncDec name (replicate (length args + 1) Parser.Any)
433+
let fun = Parser.Function [def] dec
434+
_ <- compileExpr fun
435+
lets' <- gets functions
436+
let fullName = (fromJust $ findAnyFunction (curCon ++ "@" ++ name) lets').funame
437+
return [PushPf fullName 0]
431438
compileExpr (Parser.Pipeline a (Parser.Var b _)) = compileExpr (Parser.FuncCall b [a] zeroPosition)
432439
compileExpr (Parser.Pipeline a (Parser.FuncCall f args _)) = compileExpr (Parser.FuncCall f (a : args) zeroPosition)
433440
compileExpr (Parser.Pipeline a (Parser.Then b c)) = compileExpr (Parser.Then (Parser.Pipeline a b) c)

lib/Parser.hs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ identifier = do
156156
else return x
157157

158158
integer :: Parser Integer
159-
integer = lexeme L.decimal
159+
integer =
160+
lexeme
161+
( try (char '0' *> char 'x' *> L.hexadecimal)
162+
<|> try L.decimal
163+
)
160164

161165
float :: Parser Float
162166
float = lexeme L.float
@@ -443,7 +447,8 @@ recover = withRecovery recover'
443447
return Placeholder
444448

445449
typeLiteral :: Parser Expr
446-
typeLiteral = TypeLit <$> validType
450+
typeLiteral = do
451+
TypeLit <$> validType
447452

448453
trait :: Parser Expr
449454
trait = do
@@ -503,7 +508,6 @@ term =
503508
, try funcDec
504509
, try lambda
505510
, try structLit
506-
, typeLiteral
507511
, array
508512
, try funcCall
509513
, try arrayAccess

lib/Util.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module Util where
22

3+
import Control.Monad
4+
35
concatMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]
46
concatMapM f xs = concat <$> mapM f xs
57

@@ -11,3 +13,6 @@ startsWith :: (Eq a) => [a] -> [a] -> Bool
1113
startsWith [] _ = True
1214
startsWith _ [] = False
1315
startsWith (x : xs) (y : ys) = x == y && startsWith xs ys
16+
17+
firstJust :: (a -> Maybe b) -> [a] -> Maybe b
18+
firstJust f = foldr (\x r -> f x `mplus` r) Nothing

lib/VM.hs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ data Data
161161
| DList [Data]
162162
| DNone
163163
| DChar Char
164-
| DFuncRef String [Data]
164+
| DFuncRef String [Data] [(String, Data)]
165165
| DMap (Data.Map String Data)
166166
| DTypeQuery String
167167
| DCPtr WordPtr
@@ -185,7 +185,7 @@ instance Show Data where
185185
show (DList x) = show x
186186
show DNone = "None"
187187
show (DChar x) = show x
188-
show (DFuncRef x args) = "<" ++ x ++ "(" ++ show args ++ ")>"
188+
show (DFuncRef x args _) = "<" ++ x ++ "(" ++ show args ++ ")>"
189189
show (DMap x) = show x
190190
show (DTypeQuery x) = "TypeQuery " ++ x
191191
show (DCPtr x) = "CPtr " ++ show x
@@ -320,6 +320,31 @@ run' program = do
320320
modify $ \vm -> vm{pc = vm.pc + 1}
321321
gets running >>= flip when (run' program)
322322

323+
instance Real Data where
324+
toRational (DInt x) = toRational x
325+
toRational (DFloat x) = toRational x
326+
toRational (DDouble x) = toRational x
327+
toRational x = error $ "Cannot convert " ++ show x ++ " to Rational"
328+
329+
instance Enum Data where
330+
toEnum = DInt
331+
fromEnum (DInt x) = x
332+
fromEnum (DFloat x) = round x
333+
fromEnum (DDouble x) = round x
334+
fromEnum x = error $ "Cannot convert " ++ show x ++ " to Int"
335+
336+
instance Integral Data where
337+
quot (DInt x) (DInt y) = DInt $ quot x y
338+
quot _ _ = undefined
339+
rem (DInt x) (DInt y) = DInt $ rem x y
340+
rem _ _ = undefined
341+
quotRem (DInt x) (DInt y) = (DInt $ quot x y, DInt $ rem x y)
342+
quotRem _ _ = undefined
343+
toInteger (DInt x) = toInteger x
344+
toInteger (DFloat x) = round x
345+
toInteger (DDouble x) = round x
346+
toInteger x = error $ "Cannot convert " ++ show x ++ " to Integer"
347+
323348
instance Num Data where
324349
(+) (DInt x) (DInt y) = DInt $ x + y
325350
(+) (DFloat x) (DFloat y) = DFloat $ x + y
@@ -435,6 +460,7 @@ instance Storable Data where
435460
alignment _ = 4
436461
peek _ = error "peek"
437462
poke ptr (DInt x) = poke (castPtr ptr) x
463+
poke ptr (DFloat x) = poke (castPtr ptr) x
438464
poke ptr (DString x) = poke (castPtr ptr) (unsafePerformIO $ newCString x)
439465
poke ptr (DMap x) = do
440466
let values = Data.Map.elems (clearMap x)
@@ -561,7 +587,8 @@ runInstruction (Push d) = stackPush d
561587
-- runInstruction (PushPf name nArgs) = stackPopN nArgs >>= \args -> stackPush $ DFuncRef name args
562588
runInstruction (PushPf name nArgs) = do
563589
(label, _) <- findLabelFuzzy name
564-
stackPopN nArgs >>= \args -> stackPush $ DFuncRef label args
590+
locals <- gets (locals . safeHead . callStack)
591+
stackPopN nArgs >>= \args -> stackPush $ DFuncRef label args locals
565592
runInstruction Pop = void stackPop
566593
runInstruction StackLength = stackLen >>= stackPush . DInt . fromIntegral
567594
-- Arithmetic
@@ -575,8 +602,7 @@ runInstruction Abs =
575602
DInt num -> DInt $ abs num
576603
DFloat num -> DFloat $ abs num
577604
_ -> error $ "Cannot take absolute value of " ++ show x
578-
-- runInstruction Mod = stackPopN 2 >>= \[y, x] -> stackPush $ x `mod` y
579-
runInstruction Mod = error "Mod not implemented"
605+
runInstruction Mod = stackPopN 2 >>= \[y, x] -> stackPush $ x `mod` y
580606
-- IO
581607
runInstruction (Builtin Print) = do
582608
vm <- get
@@ -610,9 +636,10 @@ runInstruction (Call x) = modify $ \vm -> vm{pc = fromMaybe (error $ "Label not
610636
runInstruction (CallLocal x) = modify $ \vm -> vm{pc = fromMaybe (error $ "Label not found: " ++ x) $ lookup x $ labels vm, callStack = StackFrame{returnAddress = pc vm, locals = (head (callStack vm)).locals} : callStack vm}
611637
runInstruction CallS =
612638
stackPop >>= \d -> case d of
613-
DFuncRef x args -> do
639+
DFuncRef x args locals -> do
614640
stackPushN args
615641
runInstruction $ Call x
642+
forM_ locals $ \(name, value) -> runInstruction (Push value) >> runInstruction (LStore name)
616643
_ -> error $ "Cannot call " ++ show d
617644
runInstruction (Jmp x) = do
618645
(_, n) <- findLabelFuzzy x
@@ -696,6 +723,7 @@ runInstruction Length =
696723
_ -> stackPop >>= \case DList l -> stackPush $ DInt $ length l; DString s -> stackPush $ DInt $ length s; _ -> error "Invalid type for length"
697724
-- Type
698725
runInstruction Cast = do
726+
-- stackPopN 2 >>= \(x : y : _) -> stackPushN [y, x]
699727
to <- stackPop
700728
stackPop >>= \case
701729
(DInt x) -> stackPush $ case to of
@@ -755,7 +783,7 @@ runInstruction TypeOf =
755783
DList _ -> stackPush $ DString "List"
756784
DNone -> stackPush $ DString "None"
757785
DChar _ -> stackPush $ DString "Char"
758-
DFuncRef _ _ -> stackPush $ DString "FuncRef"
786+
DFuncRef{} -> stackPush $ DString "FuncRef"
759787
DMap m -> do
760788
case Data.Map.lookup "__name" m of
761789
Just (DString name) -> stackPush $ DString name
@@ -776,7 +804,7 @@ runInstruction TypeEq =
776804
(DList _, DList _) -> True
777805
(DNone, DNone) -> True
778806
(DChar _, DChar _) -> True
779-
(DFuncRef _ _, DFuncRef _ _) -> True
807+
(DFuncRef{}, DFuncRef{}) -> True
780808
(DMap a, DMap b) -> do
781809
not (isJust (Data.Map.lookup "__name" a) && isJust (Data.Map.lookup "__name" b)) || (Data.Map.lookup "__name" a == Data.Map.lookup "__name" b)
782810
(DMap m, DTypeQuery tq) -> do
@@ -792,7 +820,7 @@ runInstruction TypeEq =
792820
(DList _, DTypeQuery s) -> s == "List"
793821
(DNone, DTypeQuery s) -> s == "None"
794822
(DChar _, DTypeQuery s) -> s == "Char"
795-
(DFuncRef _ _, DTypeQuery s) -> s == "FuncRef"
823+
(DFuncRef{}, DTypeQuery s) -> s == "FuncRef"
796824
_ -> False
797825
runInstruction (PackList n) = stackPopN n >>= stackPush . DList
798826
runInstruction (Mov n dat) = do

lib/Verifier.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ verifyExpr (Parser.Import{objects = o, from = from, as = as, qualified = qualifi
229229
mangleAST (Parser.Function fdef dec) alias = Parser.Function (map (`mangleAST` alias) fdef) (mangleAST dec alias)
230230
mangleAST (Parser.FuncDef name args body) alias = Parser.FuncDef (alias ++ "@" ++ name) args (mangleAST body alias)
231231
mangleAST x _ = x
232+
verifyExpr (Parser.Cast _ _) = return [] -- TODO
232233
verifyExpr x = do
233234
modify (\state -> state{topLevel = False})
234235
concatMapM verifyExpr (children x)

0 commit comments

Comments
 (0)