Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature field access #274

Merged
merged 10 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions spec/CSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,42 @@ spec = do
}
|] `shouldBe` cContext (Switch (Reference "a") [(MuNumber 1, Break None), (MuNumber 2, Continue None)] (MuNumber 1))

it "does not parse structs access" $ do
it "does parse structs access" $ do
run [text|
int main () {
person.age;
}
|] `shouldBe` cContext (Other (Just ("CMember (CVar (Ident \"person\" 243067487 (NodeInfo <no file> (<no file>,6) (Name {nameId = 4}))) " ++
"(NodeInfo <no file> (<no file>,6) (Name {nameId = 5}))) (Ident \"age\" 1668065 (NodeInfo <no file> (<no file>,3) " ++
"(Name {nameId = 6}))) False (NodeInfo <no file> (<no file>,3) (Name {nameId = 7}))")) Nothing)
|] `shouldBe` cContext (FieldReference (Reference "person") "age")

it "parses simple assignment" $ do
it "does parse expression struct access" $ do
run [text|
int main () {
f_person().age;
}
|] `shouldBe` cContext (FieldReference (Application (Reference "f_person") []) "age")

it "does parse struct field assignment" $ do
run [text|
int main () {
person.age = 10;
}
|] `shouldBe` cContext (FieldAssignment (Reference "person") "age" (MuNumber 10))

it "does parse struct pointer field assignment" $ do
run [text|
int main () {
person->age = 10;
}
|] `shouldBe` cContext (Other (Just "CMember (CVar (Ident \"person\" 243067487 (NodeInfo <no file> (<no file>,6) (Name {nameId = 4}))) (NodeInfo <no file> (<no file>,6) (Name {nameId = 5}))) (Ident \"age\" 1668065 (NodeInfo <no file> (<no file>,3) (Name {nameId = 6}))) True (NodeInfo <no file> (<no file>,3) (Name {nameId = 7}))") Nothing)

it "does parse struct pointer field assignment operation" $ do
run [text|
int main () {
person.age += 10;
}
|] `shouldBe` cContext (FieldAssignment (Reference "person") "age" (Application (Primitive Plus) [Reference "age", MuNumber 10]))

it "parses complex c example" $ do
run [text|
int cantidadDeNumerosImpares(int unosNumeros[]) {
int cantidadDeImpares;
Expand Down
6 changes: 6 additions & 0 deletions spec/JavaScriptSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ spec = do
it "handles this" $ do
js "this" `shouldBe` Self

it "handles field access" $ do
js "x.y" `shouldBe` (FieldReference (Reference "x") "y")

it "handles field assignment" $ do
js "x.y = 4" `shouldBe` (FieldAssignment (Reference "x") "y" (MuNumber (4.0)))

it "handles booleans" $ do
js "true" `shouldBe` MuTrue

Expand Down
28 changes: 28 additions & 0 deletions spec/JavaSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,34 @@ spec = do
VariableSignature "foo" "int" [],
Attribute "foo" (MuNumber 4)])

it "parses attribute access" $ do
run [text|class Foo {
public int foo(M m) {
return m.x;
}
}|] `shouldBe` Class "Foo" Nothing (Sequence [
SubroutineSignature "foo" ["M"] "int" [],
(SimpleMethod "foo" [VariablePattern "m"] (Return (FieldReference (Reference "m") "x")))])


it "parses attribute assignment" $ do
run [text|class Foo {
public void foo(M m) {
m.x = 3;
}
}|] `shouldBe` Class "Foo" Nothing (Sequence [
SubroutineSignature "foo" ["M"] "void" [],
(SimpleMethod "foo" [VariablePattern "m"] (FieldAssignment (Reference "m") "x" (MuNumber 3)))])

it "parses complex attribute assignment" $ do
run [text|class Foo {
public void foo(M m) {
m.x.y = 3;
}
}|] `shouldBe` Class "Foo" Nothing (Sequence [
SubroutineSignature "foo" ["M"] "void" [],
(SimpleMethod "foo" [VariablePattern "m"] (FieldAssignment (FieldReference (Reference "m") "x") "y" (MuNumber 3)))])

context "assertions" $ do
let wrapped expression = Class "Foo" Nothing (Sequence [
TypeSignature "test" (ParameterizedType [] "void" []),
Expand Down
6 changes: 6 additions & 0 deletions spec/PythonSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ except:
it "parses yields" $ do
py "yield 1" `shouldBe` Yield (MuNumber 1)

it "parses field access" $ do
py "x.y" `shouldBe` (FieldReference (Reference "x") "y")

it "parses field assignment" $ do
py "x.y = 2" `shouldBe` (FieldAssignment (Reference "x") "y" (MuNumber 2))

it "parses test groups" $ do
run [text|
class TestGroup(unittest.TestCase):
Expand Down
13 changes: 9 additions & 4 deletions src/Language/Mulang/Ast.hs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ data Expression
| PrimitiveMethod Operator SubroutineBody
| Variable Identifier Expression
| Assignment Identifier Expression
| FieldAssignment Expression Identifier Expression
-- ^ Generic nested field assignment
| Attribute Identifier Expression
-- ^ Object oriented programming attribute declaration, composed by an identifier and an initializer
| Object Identifier Expression
Expand Down Expand Up @@ -138,6 +140,8 @@ data Expression
-- ^ Logic programming universal cuantification
| Reference Identifier
-- ^ Generic variable
| FieldReference Expression Identifier
-- ^ Generic nested field access
| Primitive Operator
-- ^ Reference to special, low level, universal operations like logical operaions and math, that may or may not be primitives
-- in the original language
Expand Down Expand Up @@ -304,10 +308,11 @@ equationPatterns :: Equation -> [Pattern]
equationPatterns (Equation p _) = p

extractUnification :: Expression -> Maybe (Identifier, Expression)
extractUnification (Assignment name value) = Just (name, value)
extractUnification (Variable name value) = Just (name, value)
extractUnification (Attribute name value) = Just (name, value)
extractUnification _ = Nothing
extractUnification (Assignment name value) = Just (name, value)
extractUnification (FieldAssignment _ name value) = Just (name, value)
extractUnification (Variable name value) = Just (name, value)
extractUnification (Attribute name value) = Just (name, value)
extractUnification _ = Nothing

extractSubroutine :: Expression -> Maybe (Identifier, SubroutineBody)
extractSubroutine (Function name body) = Just (name, body)
Expand Down
3 changes: 3 additions & 0 deletions src/Language/Mulang/Generator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ expressions expr = expr : concatMap expressions (subExpressions expr)
subExpressions (Class _ _ v) = [v]
subExpressions (Clause _ _ es) = es
subExpressions (EntryPoint _ e) = [e]
subExpressions (FieldAssignment r _ e) = [r, e]
subExpressions (FieldReference r _) = [r]
subExpressions (For stmts a) = statementsExpressions stmts ++ [a]
subExpressions (Forall e1 e2) = [e1, e2]
subExpressions (ForLoop i c p s) = [i, c, p, s]
Expand Down Expand Up @@ -159,6 +161,7 @@ declarationsOf b = boundDeclarations (named b)

extractReference :: Expression -> Maybe Identifier
extractReference (Reference n) = Just n
extractReference (FieldReference _ n) = Just n
extractReference (Exist n _) = Just n
extractReference _ = Nothing

Expand Down
12 changes: 9 additions & 3 deletions src/Language/Mulang/Parsers/C.hs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,11 @@ muExpression (CConst constant) = muConst constant
muExpression (CVar i _) = Reference $ muIdent i
muExpression (CBinary operator leftArgument rightArgument _ ) = Application (muBinaryOp operator) [muExpression leftArgument, muExpression rightArgument]
muExpression (CUnary operator argument _ ) = muUnaryOp operator (muExpression argument)
muExpression (CAssign CAssignOp (CVar i _) rightArgument _ ) = Assignment (muIdent i) $ muExpression rightArgument
muExpression (CAssign operator l@(CVar i _) rightArgument _ ) = Assignment (muIdent i) $ Application (muAssignOp operator) [muExpression l, muExpression rightArgument]
muExpression (CAssign operator leftArgument rightArgument _ ) = muAssignmentExpression operator leftArgument rightArgument
muExpression (CCall callee arguments _ ) = Application (muExpression callee) (map muExpression arguments)
muExpression (CIndex callee argument _ ) = Application (Reference "[]") [muExpression callee, muExpression argument]
muExpression (CMember expr ident False _) = FieldReference (muExpression expr) (muIdent ident)
muExpression a = debug a
--muExpression (CMember (CExpression _) Ident Bool _ ) = undefined
--muExpression (CComma [CExpression _] _ ) = undefined
--muExpression (CCond (CExpression _) (Maybe (CExpression _)) (CExpression _) _ ) = undefined
--muExpression (CCast (CDeclaration _) (CExpression _) _ ) = undefined
Expand All @@ -118,6 +117,13 @@ muExpression a = debug a
--muExpression (CLabAddrExpr Ident _ ) = undefined
--muExpression (CBuiltinExpr (CBuiltinThing _)) = undefined

muAssignmentExpression :: CAssignOp -> CExpr -> CExpr -> Expression
muAssignmentExpression CAssignOp (CVar i _) argument = Assignment (muIdent i) $ muExpression argument
muAssignmentExpression CAssignOp (CMember exp i False _) argument = FieldAssignment (muExpression exp) (muIdent i) $ muExpression argument
muAssignmentExpression operator l@(CVar i _) argument = Assignment (muIdent i) $ Application (muAssignOp operator) [muExpression l, muExpression argument]
muAssignmentExpression operator (CMember exp i False _) argument = FieldAssignment (muExpression exp) (muIdent i) $ Application (muAssignOp operator) [Reference (muIdent i), muExpression argument]
muAssignmentExpression _ e _ = debug e

muBinaryOp :: CBinaryOp -> Expression
muBinaryOp CMulOp = Primitive O.Multiply
muBinaryOp CDivOp = Primitive O.Divide
Expand Down
16 changes: 13 additions & 3 deletions src/Language/Mulang/Parsers/Java.hs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ muExp This = Self
muExp (BinOp arg1 op arg2) = Send (muExp arg1) (muOp op) [muExp arg2]
muExp (Cond cond ifTrue ifFalse) = If (muExp cond) (muExp ifTrue) (muExp ifFalse)
muExp (ExpName name) = muName name
muExp (Assign lhs EqualA exp) = Assignment (muLhs lhs) (muExp exp)
muExp (Assign (NameLhs n) EqualA exp) = muAssignment n (muExp exp)
muExp (InstanceCreation _ clazz args _) = New (Reference $ r clazz) (map muExp args)
muExp (PreNot exp) = PrimitiveSend (muExp exp) O.Negation []
muExp (Lambda params exp) = M.Lambda (muLambdaParams params) (muLambdaExp exp)
Expand All @@ -127,9 +127,18 @@ muLambdaParams (LambdaFormalParams params) = map muFormalParam params
muCatch :: Catch -> (Pattern, Expression)
muCatch (Catch param block) = (TypePattern (muFormalParamType param), muBlock block)

muLhs (NameLhs (Name names)) = ns names
muAssignment (Name [name]) exp = Assignment (i name) exp
muAssignment (Name ns) exp = FieldAssignment r f exp
where (r, f) = foldReferences ns

muName (Name names) = Reference . ns $ names
muName (Name [name]) = Reference (i name)
muName (Name ns) = FieldReference r f
where (r, f) = foldReferences ns

foldReferences = foldReferences' . map i

foldReferences' :: [Identifier] -> (Expression, Identifier)
foldReferences' (n:ns) = (foldl (\a e -> FieldReference a e) (Reference n) (init ns), last ns)

muLit (String s) = MuString s
muLit (Char c) = MuChar c
Expand Down Expand Up @@ -222,4 +231,5 @@ r (ClassType [(name, _)]) = i name

j = parser compilationUnit

ns :: [Ident] -> String
ns = intercalate "." . map i
8 changes: 6 additions & 2 deletions src/Language/Mulang/Parsers/JavaScript.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ muJSStatement (JSLabelled _ _ statement) = mu
muJSStatement (JSEmptyStatement _) = None
muJSStatement (JSExpressionStatement (JSIdentifier _ val) _) = Reference val
muJSStatement (JSExpressionStatement expression _) = muJSExpression expression
muJSStatement (JSAssignStatement (JSIdentifier _ name) op value _) = Assignment name (muJSAssignOp op name (muJSExpression value))
muJSStatement (JSAssignStatement to op value _) = muAssignment to op (muJSExpression value)
muJSStatement (JSMethodCall (JSMemberDot receptor _ message) _ params _ _) = normalizeReference $ Send (muJSExpression receptor) (muJSExpression message) (muJSExpressionList params)
muJSStatement (JSMethodCall ident _ params _ _) = normalizeReference $ Application (muJSExpression ident) (muJSExpressionList params)
muJSStatement (JSReturn _ maybeExpression _) = Return (maybe None muJSExpression maybeExpression)
Expand All @@ -73,6 +73,10 @@ normalizeReference (Application (Reference "context") [description, L
normalizeReference (Application (Reference "it") [description, Lambda [] e]) = Test description e
normalizeReference e = e

muAssignment (JSIdentifier _ name) op value = Assignment name (muJSAssignOp op name value)
muAssignment (JSMemberDot expr1 _ (JSIdentifier _ name)) op value = FieldAssignment (muJSExpression expr1) name (muJSAssignOp op name value)
muAssignment other op value = MuTuple [debug other, debug op, debug value]

mapJSList :: (a -> b) -> JSCommaList a -> [b]
mapJSList f = map f . muJSCommaList

Expand Down Expand Up @@ -147,7 +151,7 @@ muJSExpression (JSExpressionPostfix (JSIdentifier _ name) op) = Assignment
muJSExpression (JSExpressionTernary condition _ trueVal _ falseVal) = If (muJSExpression condition) (muJSExpression trueVal) (muJSExpression falseVal)
muJSExpression (JSFunctionExpression _ ident _ params _ body) = muComputation ident params body
muJSExpression (JSArrowExpression params _ body) = Lambda (muJSArrowParameterList params) (muJSStatement body)
muJSExpression (JSMemberDot receptor _ (JSIdentifier _ message)) = Send (muJSExpression receptor) (Reference message) []
muJSExpression (JSMemberDot receptor _ (JSIdentifier _ message)) = FieldReference (muJSExpression receptor) message
muJSExpression (JSMemberExpression id _ params _) = Application (muJSExpression id) (muJSExpressionList params)
muJSExpression (JSMemberNew _ (JSIdentifier _ name) _ args _) = New (Reference name) (muJSExpressionList args)
muJSExpression (JSMemberSquare receptor _ index _) = Send (muJSExpression receptor) (Reference "[]") [muJSExpression index]
Expand Down
10 changes: 8 additions & 2 deletions src/Language/Mulang/Parsers/Python.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ muStatement (For targets generator body _ _) = M.For [M.Generator (M.TuplePatte
muStatement (Fun name args _ body _) = muComputation (muIdent name) (map muParameter args) (muSuite body)
muStatement (Class name parents body _) = muClass (listToMaybe . map muParent $ parents) (muIdent name) (muSuite body)
muStatement (Conditional guards els _ ) = foldr muIf (muSuite els) guards
muStatement (Assign [to] from _) = M.Assignment (muVariable to) (muExpr from)
muStatement (AugmentedAssign to op from _) = M.Assignment (muVariable to) (M.Application (muAssignOp $ op) [M.Reference . muVariable $ to, muExpr from])
muStatement (Assign [to] from _) = muAssignment to (muExpr from)
muStatement (AugmentedAssign to op from _) = muAssignment to (M.Application (muAssignOp $ op) [muExpr to, muExpr from])
--muStatement (Decorated
-- { decorated_decorators :: [Decorator annot] -- ^ Decorators.
-- , decorated_def :: Statement annot -- ^ Function or class definition to be decorated.
Expand Down Expand Up @@ -129,6 +129,7 @@ muExpr :: ExprSpan -> M.Expression
muExpr (Var (Ident "True" _) _) = M.MuTrue
muExpr (Var (Ident "False" _) _) = M.MuFalse
muExpr (Var ident _) = M.Reference (muIdent ident)
muExpr (Dot expr ident _) = M.FieldReference (muExpr expr) (muIdent ident)
muExpr (Int value _ _) = muNumberFromInt value
muExpr (LongInt value _ _) = muNumberFromInt value
muExpr (Float value _ _) = M.MuNumber value
Expand Down Expand Up @@ -195,6 +196,11 @@ muNumberFromInt = M.MuNumber . fromInteger

muVariable :: ExprSpan -> M.Identifier
muVariable (Var ident _) = muIdent ident
muVariable other = error (show other)

muAssignment :: ExprSpan -> M.Expression -> M.Expression
muAssignment (Var ident _) = M.Assignment (muIdent ident)
muAssignment (Dot expr ident _) = M.FieldAssignment (muExpr expr) (muIdent ident)

muArgument (ArgExpr expr _) = muExpr expr
muArgument (ArgVarArgsPos expr _ ) = muExpr expr
Expand Down