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