never executed always true always false
1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE ImportQualifiedPost #-}
3 {-# LANGUAGE LambdaCase #-}
4 {-# LANGUAGE NamedFieldPuns #-}
5 {-# LANGUAGE OverloadedStrings #-}
6 {-# OPTIONS_GHC -Wno-type-defaults -Wno-incomplete-uni-patterns #-}
7
8 {- |
9 Module : NITTA.Frontends.Lua
10 Description : Lua frontend prototype
11 Copyright : (c) Aleksandr Penskoi, 2019
12 License : BSD3
13 Maintainer : aleksandr.penskoi@gmail.com
14 Stability : experimental
15
16 This module analyzes an abstract syntax tree of the Lua language source code, provided by Language.Lua module,
17 and stores it into a NITTA's data flow graph.
18
19 Supported Lua costructions are:
20
21 - Simple math operators (addition, subtraction, multiplication and division);
22 - Variable assignments;
23 - Bitwise left and right shifts;
24 - Recursive calls.
25
26 The naming of variables in the output dataflow graph:
27
28 @
29 x^1#2 -- for variables
30 | | |
31 | | +-- value access number (one for each), e.g.
32 | | x = 1; send(x); reg(x) -- two accesses
33 | |
34 | +---- value assignment number (one for each, optional)
35 | x = f(1); x = g(2) -- two assignments
36 |
37 +------ original variable name
38
39 !123#3 -- for constant
40 | |
41 | +--- value access number
42 |
43 +------ value: 123
44
45 _a#4 -- for an unnamed variable (example see below)
46 | |
47 | +--- value access number
48 |
49 +----- char of unnamed variable (a, b..., aa, ab, ...)
50 @
51
52 Example:
53
54 >>> :{
55 void $ mapM print $ functions (frDataFlow $ translateLua $ T.pack $ unlines
56 [ "function f()"
57 , " local a = 1 + 2 + 3"
58 , " local b = a + 4 + 5"
59 , " b = b * 1 + 2"
60 , " c, d = b / 2"
61 , " send(b)"
62 , "end"
63 , "f()"
64 ] :: DataFlowGraph String Int)
65 :}
66 const(1) = !1#0 = !1#1
67 const(2) = !2#0 = !2#1 = !2#2
68 !1#0 + !2#0 = _0#a
69 const(3) = !3#0
70 _0#a + !3#0 = a^0#0
71 const(4) = !4#0
72 a^0#0 + !4#0 = _0#b
73 const(5) = !5#0
74 _0#b + !5#0 = b^0#0
75 b^0#0 * !1#1 = _1#b
76 _1#b + !2#1 = b^1#0 = b^1#1
77 !2#2 / b^1#0 = _; !2#2 mod b^1#0 = _
78 send(b^1#1)
79 -}
80 module NITTA.Frontends.Lua (
81 translateLua,
82 FrontendResult (..),
83 TraceVar (..),
84
85 -- * Internal
86 LuaAlgBuilder (..),
87 LuaStatement (..),
88 LuaValueInstance (..),
89 buildAlg,
90 findStartupFunction,
91 getLuaBlockFromSources,
92 processStatement,
93 ) where
94
95 import Control.Monad.State
96 import Data.HashMap.Strict qualified as HM
97 import Data.Hashable
98 import Data.Maybe
99 import Data.String
100 import Data.String.ToString
101 import Data.Text qualified as T
102 import Language.Lua hiding (Var)
103 import NITTA.Frontends.Common
104 import NITTA.Intermediate.DataFlow
105 import NITTA.Intermediate.Functions qualified as F
106 import NITTA.Intermediate.Types
107 import NITTA.Utils.Base
108 import Prelude hiding (EQ, GT, LT)
109
110 getUniqueLuaVariableName LuaValueInstance{lviName, lviIsConstant = True} luaValueAccessCount = "!" <> lviName <> "#" <> showText luaValueAccessCount
111 getUniqueLuaVariableName LuaValueInstance{lviName, lviAssignCount} luaValueAccessCount
112 | T.head lviName == '_' = lviName
113 | otherwise = lviName <> "^" <> showText lviAssignCount <> "#" <> showText luaValueAccessCount
114
115 data LuaStatement x = LuaStatement
116 { fIn :: [T.Text]
117 , fOut :: [LuaValueInstance]
118 , fName :: T.Text
119 , fValues :: [x]
120 , fInt :: [Int]
121 }
122 deriving (Show, Eq)
123
124 -- | Stores information about a particular version of a variable. The version of a variable changes after assigning a new value to it.
125 data LuaValueInstance = LuaValueInstance
126 { lviName :: T.Text
127 , lviAssignCount :: Int
128 , lviIsConstant :: Bool
129 }
130 deriving (Show, Eq)
131
132 instance Hashable LuaValueInstance where
133 hashWithSalt i LuaValueInstance{lviName, lviAssignCount, lviIsConstant} =
134 ( (hashWithSalt i lviName * 31)
135 + hashWithSalt i lviAssignCount
136 )
137 * 31
138 + hashWithSalt i lviIsConstant
139
140 data LuaAlgBuilder x = LuaAlgBuilder
141 { algGraph :: [LuaStatement x]
142 -- ^ A list containing all expressions to be added to the final graph.
143 , algLatestLuaValueInstance :: HM.HashMap T.Text LuaValueInstance
144 -- ^ A table that maps a variable name to the most recent corresponding LuaValueInstance.
145 , algVarCounters :: HM.HashMap T.Text Int
146 -- ^ A table needed to generate unique temporary variable names.
147 , algVars :: HM.HashMap LuaValueInstance [T.Text]
148 -- ^ A table lists all uses of a particular LuaValueInstance.
149 , algStartupArgs :: HM.HashMap Int (T.Text, T.Text)
150 -- ^ Map argument index to the variable name and initial value (in text).
151 , algConstants :: HM.HashMap T.Text LuaValueInstance
152 -- ^ A table correlating constant with LuaValueInstance which store this constant.
153 , algTraceFuncs :: [([T.Text], Maybe T.Text)]
154 -- ^ A list that stores debug information about monitored variables and their display formats.
155 }
156 deriving (Show)
157
158 -- left part of lua statement
159 parseLeftExp (VarName (Name v)) = v
160 parseLeftExp var = error $ "unexpected lua variable declaration format : " <> show var
161
162 -- right part of lua statement
163 parseRightExp [fOut] (Binop ShiftL a (Number IntNum s)) = do
164 varName <- parseExpArg fOut a
165 addVariable [varName] [fOut] [] "shiftL" [readText s]
166 parseRightExp [fOut] (Binop ShiftR a (Number IntNum s)) = do
167 varName <- parseExpArg fOut a
168 addVariable [varName] [fOut] [] "shiftR" [readText s]
169 parseRightExp [fOut] (Number _ valueString) = do
170 addVariable [] [fOut] [readText valueString] "constant" []
171 parseRightExp fOut@(x : _) (Binop op a b) = do
172 varNameA <- parseExpArg x a
173 varNameB <- parseExpArg x b
174 addVariable [varNameA, varNameB] fOut [] (getBinopFuncName op) []
175 where
176 getBinopFuncName Add = "add"
177 getBinopFuncName Sub = "sub"
178 getBinopFuncName Mul = "multiply"
179 getBinopFuncName Div = "divide"
180 getBinopFuncName LT = "lessThan"
181 getBinopFuncName LTE = "lessThanOrEqual"
182 getBinopFuncName EQ = "equal"
183 getBinopFuncName GTE = "greaterThanOrEqual"
184 getBinopFuncName GT = "greaterThan"
185 getBinopFuncName And = "and"
186 getBinopFuncName Or = "or"
187 getBinopFuncName o = error $ "unknown binop: " <> show o
188 parseRightExp fOut (PrefixExp (Paren e)) = parseRightExp fOut e
189 parseRightExp fOut (Unop Neg (Number numType name)) = parseRightExp fOut (Number numType ("-" <> name))
190 parseRightExp [fOut] (Unop Neg expr@(PrefixExp _)) = do
191 varName <- parseExpArg fOut expr
192 addVariable [varName] [fOut] [] "neg" []
193 parseRightExp fOut (Unop Not (Number numType name)) = parseRightExp fOut (Number numType ("not" <> name))
194 parseRightExp [fOut] (Unop Not expr@(PrefixExp _)) = do
195 varName <- parseExpArg fOut expr
196 addVariable [varName] [fOut] [] "not" []
197 parseRightExp
198 [fOut]
199 ( PrefixExp
200 ( PEFunCall
201 ( NormalFunCall
202 (PEVar (VarName (Name fname)))
203 (Args args)
204 )
205 )
206 ) = do
207 fIn <- mapM (parseExpArg fOut) args
208 addFunction fname fIn [fOut]
209 parseRightExp [fOut] (PrefixExp (PEVar (VarName (Name name)))) = do
210 addAlias fOut name
211 parseRightExp _ expr = error $ "unknown expression : " <> show expr
212
213 parseExpArg _ n@(Number _ _) = do
214 addConstant n
215 parseExpArg fOut expr@(Unop Neg _) = do
216 name <- getNextTmpVarName fOut
217 _ <- parseRightExp [name] expr
218 addVariableAccess name
219 parseExpArg _ (PrefixExp (PEVar (VarName (Name name)))) = do
220 addVariableAccess name
221 parseExpArg fOut binop@Binop{} = do
222 name <- getNextTmpVarName fOut
223 _ <- parseRightExp [name] binop
224 addVariableAccess name
225 parseExpArg fOut (PrefixExp (Paren arg)) = parseExpArg fOut arg
226 parseExpArg fOut call@(PrefixExp (PEFunCall _)) = do
227 name <- getNextTmpVarName fOut
228 _ <- parseRightExp [name] call
229 addVariableAccess name
230 parseExpArg _ _ = undefined
231
232 getNextTmpVarName fOut
233 | T.isInfixOf "#" fOut = getNextTmpVarName (T.splitOn "#" fOut !! 1)
234 | otherwise = do
235 luaAlgBuilder@LuaAlgBuilder{algVarCounters} <- get
236 case HM.lookup fOut algVarCounters of
237 Just value -> do
238 put luaAlgBuilder{algVarCounters = HM.insert fOut (value + 1) algVarCounters}
239 return $ "_" <> showText value <> "#" <> fOut
240 Nothing -> do
241 put luaAlgBuilder{algVarCounters = HM.insert fOut 1 algVarCounters}
242 return $ "_0#" <> fOut
243
244 addStartupFuncArgs (FunCall (NormalFunCall _ (Args exps))) (FunAssign _ (FunBody names _ _)) = do
245 mapM_
246 ( \case
247 (Name name, Number _ valueString, serialNumber) -> addToBuffer name valueString serialNumber
248 (Name name, Unop Neg (Number _ valueString), serialNumber) -> addToBuffer name ("-" <> valueString) serialNumber
249 _ -> error "addStartupFuncArgs: internal error"
250 )
251 $ zip3 names exps [0 ..]
252 return ""
253 where
254 addToBuffer name valueString serialNumber = do
255 luaAlgBuilder@LuaAlgBuilder{algVars, algLatestLuaValueInstance, algStartupArgs} <- get
256 let value = LuaValueInstance{lviName = name, lviAssignCount = 0, lviIsConstant = False}
257 put luaAlgBuilder{algLatestLuaValueInstance = HM.insert name value algLatestLuaValueInstance, algVars = HM.insert value [] algVars, algStartupArgs = HM.insert serialNumber (name, valueString) algStartupArgs}
258 return value
259 addStartupFuncArgs _ _ = undefined
260
261 -- Lua language Stat structure parsing
262 -- LocalAssign
263 processStatement _ (LocalAssign _names Nothing) = do
264 return ()
265 processStatement fn (LocalAssign names (Just exps)) =
266 processStatement fn $ Assign (map VarName names) exps
267 -- Assign
268 processStatement fn (Assign lexps@[_] [Unop Neg (Number ntype ntext)]) =
269 processStatement fn (Assign lexps [Number ntype ("-" <> ntext)])
270 processStatement _ (Assign lexp [rexp]) = do
271 parseRightExp (map parseLeftExp lexp) rexp
272 processStatement startupFunctionName (Assign vars exps) | length vars == length exps = do
273 mapM_
274 ( \case
275 (VarName (Name name), expr) -> processStatement startupFunctionName (Assign [VarName (Name (getTempAlias name))] [expr])
276 _ -> error "processStatement: internal error"
277 )
278 $ zip vars exps
279 mapM_ (\(VarName (Name name)) -> addAlias name (getTempAlias name)) vars
280 where
281 getTempAlias name = name <> "&"
282 -- startup function recursive call
283 processStatement fn (FunCall (NormalFunCall (PEVar (VarName (Name fName))) (Args args)))
284 | fn == fName = do
285 LuaAlgBuilder{algStartupArgs} <- get
286 let startupVarsNames = map (fromMaybe (error "processStatement: internal error") . (`HM.lookup` algStartupArgs)) [0 .. (HM.size algStartupArgs)]
287 let startupVarsVersions = map (\x -> LuaValueInstance{lviName = fst x, lviAssignCount = 0, lviIsConstant = False}) startupVarsNames
288 mapM_ parseStartupArg $ zip3 args startupVarsVersions (map (readText . snd) startupVarsNames)
289 where
290 parseStartupArg (arg, valueVersion, index) = do
291 varName <- parseExpArg "loop" arg
292 luaAlgBuilder@LuaAlgBuilder{algGraph} <- get
293 put luaAlgBuilder{algGraph = LuaStatement{fIn = [varName], fOut = [valueVersion], fValues = [index], fName = "loop", fInt = []} : algGraph}
294 processStatement _ (FunCall (NormalFunCall (PEVar (VarName (Name fName))) (Args args))) = do
295 fIn <- mapM (parseExpArg "tmp") args
296 addFunction (fromText fName) fIn [fromString ""]
297 processStatement _fn (FunCall (NormalFunCall (PEVar (SelectName (PEVar (VarName (Name "debug"))) (Name fName))) (Args args))) = do
298 let fIn = map parseTraceArg args
299 luaAlgBuilder@LuaAlgBuilder{algTraceFuncs, algLatestLuaValueInstance} <- get
300 case (fName, fIn) of
301 ("trace", tFmt : vs)
302 | T.isPrefixOf "\"" tFmt && T.isPrefixOf "\"" tFmt -> do
303 let vars = map (\x -> T.pack $ takeWhile (/= '#') $ T.unpack $ getUniqueLuaVariableName (fromMaybe undefined $ HM.lookup x algLatestLuaValueInstance) 0) vs
304 put luaAlgBuilder{algTraceFuncs = (vars, Just $ T.replace "\"" "" tFmt) : algTraceFuncs}
305 ("trace", vs) -> do
306 let vars = map (\x -> T.pack $ takeWhile (/= '#') $ T.unpack $ getUniqueLuaVariableName (fromMaybe undefined $ HM.lookup x algLatestLuaValueInstance) 0) vs
307 put luaAlgBuilder{algTraceFuncs = (vars, Nothing) : algTraceFuncs}
308 _ -> error $ "unknown debug method: " <> show fName <> " " <> show args
309 where
310 parseTraceArg (String s) = s
311 parseTraceArg (PrefixExp (PEVar (VarName (Name name)))) = name
312 parseTraceArg _ = undefined
313 processStatement _ _stat = error $ "unknown statement: " <> show _stat
314
315 addFunction funcName [i] fOut | toString funcName == "buffer" = do
316 addVariable [i] fOut [] "buffer" []
317 addFunction funcName [i] fOut | toString funcName == "brokenBuffer" = do
318 addVariable [i] fOut [] "brokenBuffer" []
319 addFunction funcName [i] _ | toString funcName == "send" = do
320 luaAlgBuilder@LuaAlgBuilder{algGraph} <- get
321 put luaAlgBuilder{algGraph = LuaStatement{fIn = [i], fOut = [], fValues = [], fName = "send", fInt = []} : algGraph}
322 addFunction funcName _ fOut | toString funcName == "receive" = do
323 addVariable [] fOut [] "receive" []
324 addFunction "if_mux" [cond, a, b] [c] = do
325 addVariable [cond, a, b] [c] [] "if_mux" []
326 addFunction fName _ _ = error $ "unknown function" <> T.unpack fName
327
328 addConstant (Number _valueType valueString) = do
329 luaAlgBuilder@LuaAlgBuilder{algGraph, algVars, algConstants} <- get
330 let lvv = LuaValueInstance{lviName = valueString, lviAssignCount = 0, lviIsConstant = True}
331 case HM.lookup valueString algConstants of
332 Just value -> do
333 let names = fromMaybe (error "lua constants parsing error") $ HM.lookup value algVars
334 let resultName = getUniqueLuaVariableName lvv $ length names
335 put luaAlgBuilder{algVars = HM.insert value (resultName : names) algVars}
336 return resultName
337 Nothing -> do
338 let resultName = getUniqueLuaVariableName lvv 0
339 put
340 luaAlgBuilder
341 { algGraph = LuaStatement{fIn = [], fOut = [lvv], fValues = [readText valueString], fName = "constant", fInt = []} : algGraph
342 , algVars = HM.insert lvv [resultName] algVars
343 , algConstants = HM.insert valueString lvv algConstants
344 }
345 return resultName
346 addConstant _ = undefined
347
348 addVariable fIn fOut fValues fName fInt = do
349 LuaAlgBuilder{algLatestLuaValueInstance} <- get
350 let luaValueInstances = map (\x -> nameToLuaValueInstance algLatestLuaValueInstance x) fOut
351 let func = LuaStatement{fIn, fValues, fName, fInt, fOut = luaValueInstances}
352 mapM_ (uncurry addItemToBuffer) $ zip fOut luaValueInstances
353 mapM_ addItemToVars luaValueInstances
354 luaAlgBuilder@LuaAlgBuilder{algGraph, algConstants, algLatestLuaValueInstance = algLatestLuaValueInstance'} <- get
355 case fName of
356 "constant" -> do
357 case HM.lookup (showText $ head fValues) algConstants of
358 Just lvv -> do
359 put luaAlgBuilder{algLatestLuaValueInstance = HM.insert (head fOut) lvv algLatestLuaValueInstance'}
360 Nothing -> do
361 put luaAlgBuilder{algGraph = func : algGraph, algConstants = HM.insert (showText $ head fValues) (head luaValueInstances) algConstants}
362 _ -> do
363 put luaAlgBuilder{algGraph = func : algGraph}
364 where
365 nameToLuaValueInstance algLatestLuaValueInstance name =
366 case getLuaValueByName name algLatestLuaValueInstance of
367 Just lvv@LuaValueInstance{lviAssignCount} -> lvv{lviAssignCount = lviAssignCount + 1}
368 Nothing -> LuaValueInstance{lviName = name, lviAssignCount = 0, lviIsConstant = False}
369 addItemToBuffer name lvv = do
370 luaAlgBuilder@LuaAlgBuilder{algLatestLuaValueInstance} <- get
371 put luaAlgBuilder{algLatestLuaValueInstance = HM.insert name lvv algLatestLuaValueInstance}
372 addItemToVars name = do
373 luaAlgBuilder@LuaAlgBuilder{algVars} <- get
374 put luaAlgBuilder{algVars = HM.insert name [] algVars}
375
376 addVariableAccess name = do
377 luaAlgBuilder@LuaAlgBuilder{algVars} <- get
378 luaValueInstance <- getLatestLuaValueInstanceByName name
379 case HM.lookup luaValueInstance algVars of
380 Just value -> do
381 let len = length value
382 let resultName = getUniqueLuaVariableName luaValueInstance len
383 put luaAlgBuilder{algVars = HM.insert luaValueInstance (resultName : value) algVars}
384 return resultName
385 Nothing -> error ("variable '" <> show (lviName luaValueInstance) <> " not found. Constants list : " <> show algVars)
386
387 getLatestLuaValueInstanceByName name = do
388 LuaAlgBuilder{algLatestLuaValueInstance} <- get
389 case HM.lookup name algLatestLuaValueInstance of
390 Just value -> return value
391 Nothing -> error $ "variable not found : '" <> show name <> "'."
392
393 addAlias from to = do
394 luaAlgBuilder@LuaAlgBuilder{algLatestLuaValueInstance} <- get
395 case getLuaValueByName to algLatestLuaValueInstance of
396 Just value -> do
397 put luaAlgBuilder{algLatestLuaValueInstance = HM.insert from value algLatestLuaValueInstance}
398 Nothing -> error ("variable '" <> show to <> " not found. Constants list : " <> show algLatestLuaValueInstance)
399
400 getLuaValueByName name buffer = HM.lookup name buffer
401
402 buildAlg syntaxTree =
403 flip execState emptyLuaAlgBuilder $ do
404 let (startupFunctionName, startupFunctionCall, startupFunctionDef) = findStartupFunction syntaxTree
405 statements = funAssignStatements startupFunctionDef
406 _ <- addStartupFuncArgs startupFunctionCall startupFunctionDef
407 mapM_ (processStatement startupFunctionName) statements
408 where
409 emptyLuaAlgBuilder =
410 LuaAlgBuilder
411 { algGraph = []
412 , algLatestLuaValueInstance = HM.empty
413 , algVarCounters = HM.empty
414 , algVars = HM.empty
415 , algStartupArgs = HM.empty
416 , algConstants = HM.empty
417 , algTraceFuncs = []
418 }
419 funAssignStatements (FunAssign _ (FunBody _ _ (Block statements _))) = statements
420 funAssignStatements _ = error "funAssignStatements : not a function assignment"
421
422 findStartupFunction (Block statements Nothing)
423 | [call] <- filter (\case FunCall{} -> True; _ -> False) statements
424 , [funAssign] <- filter (\case FunAssign{} -> True; _ -> False) statements
425 , (FunCall (NormalFunCall (PEVar (VarName (Name fnCall))) _)) <- call
426 , (FunAssign (FunName (Name fnAssign) _ _) _) <- funAssign
427 , fnCall == fnAssign =
428 (fnCall, call, funAssign)
429 findStartupFunction _ = error "can't find startup function in lua source code"
430
431 getLuaBlockFromSources src = either (\e -> error $ "Exception while parsing Lua sources: " <> show e) id $ parseText chunk src
432
433 alg2graph LuaAlgBuilder{algGraph, algLatestLuaValueInstance, algVars} = flip execState (DFCluster []) $ do
434 mapM addToGraph algGraph
435 where
436 addToGraph item = do
437 graph <- get
438 put (addFuncToDataFlowGraph (function2nitta item) graph)
439 return $ fromString ""
440 function2nitta LuaStatement{fName = "buffer", fIn = [i], fOut = [o], fValues = [], fInt = []} = F.buffer (fromText i) $ output o
441 function2nitta LuaStatement{fName = "brokenBuffer", fIn = [i], fOut = [o], fValues = [], fInt = []} = F.brokenBuffer (fromText i) $ output o
442 function2nitta LuaStatement{fName = "constant", fIn = [], fOut = [o], fValues = [x], fInt = []} = F.constant x $ output o
443 function2nitta LuaStatement{fName = "send", fIn = [i], fOut = [], fValues = [], fInt = []} = F.send (fromText i)
444 function2nitta LuaStatement{fName = "add", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.add (fromText a) (fromText b) $ output c
445 function2nitta LuaStatement{fName = "sub", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.sub (fromText a) (fromText b) $ output c
446 function2nitta LuaStatement{fName = "multiply", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.multiply (fromText a) (fromText b) $ output c
447 function2nitta LuaStatement{fName = "divide", fIn = [d, n], fOut = [q], fValues = [], fInt = []} = F.division (fromText d) (fromText n) (output q) []
448 function2nitta LuaStatement{fName = "divide", fIn = [d, n], fOut = [q, r], fValues = [], fInt = []} = F.division (fromText d) (fromText n) (output q) (output r)
449 function2nitta LuaStatement{fName = "neg", fIn = [i], fOut = [o], fValues = [], fInt = []} = F.neg (fromText i) $ output o
450 function2nitta LuaStatement{fName = "receive", fIn = [], fOut = [o], fValues = [], fInt = []} = F.receive $ output o
451 function2nitta LuaStatement{fName = "shiftL", fIn = [a], fOut = [c], fValues = [], fInt = [s]} = F.shiftL s (fromText a) $ output c
452 function2nitta LuaStatement{fName = "shiftR", fIn = [a], fOut = [c], fValues = [], fInt = [s]} = F.shiftR s (fromText a) $ output c
453 function2nitta LuaStatement{fName = "loop", fIn = [a], fOut = [c], fValues = [x], fInt = []} = F.loop x (fromText a) $ output c
454 function2nitta LuaStatement{fName = "lessThan", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.cmp F.CmpLt (fromText a) (fromText b) (output c)
455 function2nitta LuaStatement{fName = "lessThanOrEqual", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.cmp F.CmpLte (fromText a) (fromText b) $ output c
456 function2nitta LuaStatement{fName = "equal", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.cmp F.CmpEq (fromText a) (fromText b) $ output c
457 function2nitta LuaStatement{fName = "greaterThanOrEqual", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.cmp F.CmpGte (fromText a) (fromText b) $ output c
458 function2nitta LuaStatement{fName = "greaterThan", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.cmp F.CmpGt (fromText a) (fromText b) $ output c
459 function2nitta LuaStatement{fName = "and", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.logicAnd (fromText a) (fromText b) $ output c
460 function2nitta LuaStatement{fName = "or", fIn = [a, b], fOut = [c], fValues = [], fInt = []} = F.logicOr (fromText a) (fromText b) $ output c
461 function2nitta LuaStatement{fName = "not", fIn = [a], fOut = [c], fValues = [], fInt = []} = F.logicNot (fromText a) $ output c
462 function2nitta LuaStatement{fName = "if_mux", fIn = [cond, b, a], fOut = [c], fValues = [], fInt = []} = F.mux [fromText a, fromText b] (fromText cond) $ output c
463 function2nitta f = error $ "function not found: " <> show f
464 output v =
465 case HM.lookup v algVars of
466 Just names -> map fromText names
467 _ -> error $ "variable not found : " <> show v <> ", buffer : " <> show algLatestLuaValueInstance
468
469 translateLua :: (Var v, Val x) => T.Text -> FrontendResult v x
470 translateLua src =
471 let syntaxTree = getLuaBlockFromSources src
472 luaAlgBuilder = buildAlg syntaxTree
473 frTrace = getFrTrace $ getAllTraceFuncs luaAlgBuilder
474 in FrontendResult{frDataFlow = alg2graph luaAlgBuilder, frTrace, frPrettyLog = prettyLog frTrace}
475 where
476 getAllTraceFuncs algBuilder =
477 let traceFuncs = algTraceFuncs algBuilder
478 startupArgNames =
479 map
480 (\(_idx, (varName, _initValue)) -> varName)
481 $ HM.toList
482 $ algStartupArgs algBuilder
483 in map (\name -> ([name <> "^0"], Nothing)) startupArgNames <> traceFuncs
484
485 getFrTrace traceFuncs = [TraceVar fmt var | (vars, fmt) <- traceFuncs, var <- vars]