diff --git a/AlgebraicDataflowArchitectureModel/models/Accounts.model b/AlgebraicDataflowArchitectureModel/models/Accounts.model index 1dbffc5..dba68ba 100644 --- a/AlgebraicDataflowArchitectureModel/models/Accounts.model +++ b/AlgebraicDataflowArchitectureModel/models/Accounts.model @@ -1,7 +1,7 @@ channel CIO1 { - out accounts(l:List, signup(name:Str)) == append(l, name) + out accounts(l:Map, signup(id:Int, name:Str)) = append(l, {"name": name}) } channel CIO2(uid:Int) { - out accounts.{uid}(n:Str, changeName(name)) == name + out accounts.{uid}.name(n:Str, changeName(name)) = name } diff --git a/AlgebraicDataflowArchitectureModel/models/Algo.model b/AlgebraicDataflowArchitectureModel/models/Algo.model index 6228431..328f11a 100644 --- a/AlgebraicDataflowArchitectureModel/models/Algo.model +++ b/AlgebraicDataflowArchitectureModel/models/Algo.model @@ -1,12 +1,12 @@ channel turnA{ ref handsB(b:List, drawA(target:Int, guess:Int, b, d)) ref deck(d:List, drawA(target, guess, b, d)) - out handsA(a:List, drawA(target, guess, b, d)) == if(eq(get(b, target), guess), cons(tuple(fst(head(d)), false), a), cons(tuple(fst(head(d)), true), a)) - out handsB(a:List, drawA(target, guess, b, d)) == if(eq(get(b, target), guess), set(a, target, tuple(fst(get(a, target)), true)), a) - out deck(t:List, drawA(target, guess, b, d)) == tail(d) + out handsA(a:List, drawA(target, guess, b, d)) = if(eq(get(b, target), guess), cons(tuple(fst(head(d)), false), a), cons(tuple(fst(head(d)), true), a)) + out handsB(a:List, drawA(target, guess, b, d)) = if(eq(get(b, target), guess), set(a, target, tuple(fst(get(a, target)), true)), a) + out deck(t:List, drawA(target, guess, b, d)) = tail(d) } channel turnAA{ ref handsB(b:List, selectA(target:Int, guess:Int, attacker:Int, b)) - out handsA(a:List, selectA(target, guess, attacker, b)) == if(eq(get(b, target), guess), a, set(a, attacker, tuple(fst(get(a, attacker)), true))) - out handsB(a:List, selectA(target, guess, attacker, b)) == if(eq(get(b, target), guess), set(a, target, tuple(fst(get(a, target)), true)), a) + out handsA(a:List, selectA(target, guess, attacker, b)) = if(get(b, target) == guess, a, set(a, attacker, tuple(fst(get(a, attacker)), true))) + out handsB(a:List, selectA(target, guess, attacker, b)) = if(get(b, target) == guess, set(a, target, tuple(fst(get(a, target)), true)), a) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Algolike.model b/AlgebraicDataflowArchitectureModel/models/Algolike.model index 97aef04..8ea8dc2 100644 --- a/AlgebraicDataflowArchitectureModel/models/Algolike.model +++ b/AlgebraicDataflowArchitectureModel/models/Algolike.model @@ -6,25 +6,25 @@ guessB := 0 } channel targetAInput{ - out targetA(t:Int, setTargetA(a:Int)) == a + out targetA(t:Int, setTargetA(a:Int)) = a } channel targetBInput{ - out targetB(t:Int, setTargetB(b:Int)) == b + out targetB(t:Int, setTargetB(b:Int)) = b } channel attackerAInput{ - out attackerA(t:Int, setAttackerA(a:Int)) == a + out attackerA(t:Int, setAttackerA(a:Int)) = a } channel attackerBInput{ - out attackerB(t:Int, setAttackerB(b:Int)) == b + out attackerB(t:Int, setAttackerB(b:Int)) = b } channel guessAInput{ - out guessA(t:Int, setGuessA(a:Int)) == a + out guessA(t:Int, setGuessA(a:Int)) = a } channel guessBInput{ - out guessB(t:Int, setGuessB(b:Int)) == b + out guessB(t:Int, setGuessB(b:Int)) = b } channel addDeck{ - out deck(d:List, addCard(num:Integer)) == cons(tuple(num, false), d) + out deck(d:List, addCard(num:Integer)) = cons(tuple(num, false), d) } channel drawAInput{ @@ -32,21 +32,21 @@ ref targetA(t:Int, drawAndAttackA(t, g, b)) ref guessA(g:Int, drawAndAttackA(t, g, b)) ref handsB(b:List, drawAndAttackA(t, g, b)) - out resultByDrawingA(sda:Tuple, drawAndAttackA(t, g, b)) == tuple(eq(fst(get(b, t)), g), t) + out resultByDrawingA(sda:Tuple, drawAndAttackA(t, g, b)) = tuple(fst(get(b, t)) == g, t) } channel inputDrawArgsA{ - in resultByDrawingA(sda:Tuple, drawA(sucTrg, d)) == sucTrg + in resultByDrawingA(sda:Tuple, drawA(sucTrg, d)) = sucTrg ref deck(d:List, drawA(sucTrg, d)) - out handsA(outA:List, drawA(sucTrg, d)) == if(fst(sucTrg), - sortByKey(cons(tuple(fst(head(d)),false), outA)), + out handsA(outA:List, drawA(sucTrg, d)) = if(fst(sucTrg), + sortByKey(cons(tuple(fst(head(d)), false), outA)), sortByKey(cons(tuple(fst(head(d)), true), outA))) - out handsB(outB:List, drawA(sucTrg, d)) == if(fst(sucTrg), + out handsB(outB:List, drawA(sucTrg, d)) = if(fst(sucTrg), set(outB, snd(sucTrg), tuple(fst(get(outB, snd(sucTrg))), true)), outB) - out deck(t:List, drawA(sucTrg, d)) == tail(t) + out deck(t:List, drawA(sucTrg, d)) = tail(t) } channel selectAInput{ @@ -54,14 +54,14 @@ ref targetA(t:Int, selectAndAttackA(a, t, g, b)) ref guessA(g:Int, selectAndAttackA(a, t, g, b)) ref handsB(b:List, selectAndAttackA(a, t, g, b)) - out resultBySelectingA(ssa:Tuple, selectAndAttackA(a, t, g, b)) == tuple(eq(fst(get(b, t)), g), t, a) + out resultBySelectingA(ssa:Tuple, selectAndAttackA(a, t, g, b)) = tuple(fst(get(b, t)) == g, t, a) } channel inputSelectArgA{ - in resultBySelectingA(ssa, selectA(sucTrgAtk)) == sucTrgAtk - out handsA(outA, selectA(sucTrgAtk)) == if(fst(sucTrgAtk), + in resultBySelectingA(ssa, selectA(sucTrgAtk)) = sucTrgAtk + out handsA(outA, selectA(sucTrgAtk)) = if(fst(sucTrgAtk), outA, set(outA, snd(snd(sucTrgAtk)), tuple(fst(get(outA, snd(snd(sucTrgAtk)))), true))) - out handsB(outB, selectA(sucTrgAtk)) == if(fst(sucTrgAtk), + out handsB(outB, selectA(sucTrgAtk)) = if(fst(sucTrgAtk), set(outB, fst(snd(sucTrgAtk)), tuple(fst(get(outB, fst(snd(sucTrgAtk)))), true)), outB) } @@ -69,21 +69,21 @@ ref targetB(t:Int, drawAndAttackB(t, g, a)) ref guessB(g:Int, drawAndAttackB(t, g, a)) ref handsA(a:List, drawAndAttackB(t, g, a)) - out resultByDrawingB(sdb:Tuple, drawAndAttackB(t, g, a)) == tuple(eq(fst(get(a, t)), g), t) + out resultByDrawingB(sdb:Tuple, drawAndAttackB(t, g, a)) = tuple(fst(get(a, t)) == g, t) } channel inputDrawArgsB{ - in resultByDrawingB(sdb:Tuple, drawB(sucTrg, d)) == sucTrg + in resultByDrawingB(sdb:Tuple, drawB(sucTrg, d)) = sucTrg ref deck(d:List, drawB(sucTrg, d)) - out handsB(outB:List, drawB(sucTrg, d)) == if(fst(sucTrg), + out handsB(outB:List, drawB(sucTrg, d)) = if(fst(sucTrg), sortByKey(cons(tuple(fst(head(d)),false), outB)), sortByKey(cons(tuple(fst(head(d)), true), outB))) - out handsA(outA:List, drawB(sucTrg, d)) == if(fst(sucTrg), + out handsA(outA:List, drawB(sucTrg, d)) = if(fst(sucTrg), set(outA, snd(sucTrg), tuple(fst(get(outA, snd(sucTrg))), true)), outA) - out deck(t:List, drawB(sucTrg, d)) == tail(t) + out deck(t:List, drawB(sucTrg, d)) = tail(t) } channel selectBInput{ @@ -91,23 +91,23 @@ ref targetB(t:Int, selectAndAttackB(atk, t, g, a)) ref guessB(g:Int, selectAndAttackB(atk, t, g, a)) ref handsA(a:List, selectAndAttackB(atk, t, g, a)) - out resultBySelectingB(ssb:Tuple, selectAndAttackB(atk, t, g, a)) == tuple(eq(fst(get(a, t)), g), t, atk) + out resultBySelectingB(ssb:Tuple, selectAndAttackB(atk, t, g, a)) = tuple(fst(get(a, t)) == g, t, atk) } channel inputSelectArgB{ - in resultBySelectingB(ssb, selectB(sucTrgAtk)) == sucTrgAtk - out handsB(outB, selectB(sucTrgAtk)) == if(fst(sucTrgAtk), + in resultBySelectingB(ssb, selectB(sucTrgAtk)) = sucTrgAtk + out handsB(outB, selectB(sucTrgAtk)) = if(fst(sucTrgAtk), outB, set(outB, snd(snd(sucTrgAtk)), tuple(fst(get(outB, snd(snd(sucTrgAtk)))), true))) - out handsA(outA, selectB(sucTrgAtk)) == if(fst(sucTrgAtk), + out handsA(outA, selectB(sucTrgAtk)) = if(fst(sucTrgAtk), set(outA, fst(snd(sucTrgAtk)), tuple(fst(get(outA, fst(snd(sucTrgAtk)))), true)), outA) } channel judgeA{ - in handsA(a:List, judge(j)) == j - out loseA(la:Bool, judge(j)) == eq(length(extractFaceDown(j)), 0) + in handsA(a:List, judge(j)) = j + out loseA(la:Bool, judge(j)) = length(extractFaceDown(j)) == 0 } channel judgeB{ - in handsB(b:List, judge(j)) == j - out loseB(lb:Bool, judge(j)) == eq(length(extractFaceDown(j)), 0) + in handsB(b:List, judge(j)) = j + out loseB(lb:Bool, judge(j)) = length(extractFaceDown(j)) == 0 } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Base.model b/AlgebraicDataflowArchitectureModel/models/Base.model index ac44843..bb460e4 100644 --- a/AlgebraicDataflowArchitectureModel/models/Base.model +++ b/AlgebraicDataflowArchitectureModel/models/Base.model @@ -1,13 +1,13 @@ channel CIO{ - out r1(x1:Int, set1(y1:Int)) == y1 - out r1(x1, e) == x1 + out r1(x1:Int, set1(y1:Int)) = y1 + out r1(x1, e) = x1 } channel CIO2{ - out r2(x2:Int, set2(y2:Int)) == y2 - out r2(x2, e) == x2 + out r2(x2:Int, set2(y2:Int)) = y2 + out r2(x2, e) = x2 } channel C1{ - in r1(x1, update(x1:Int, y1:Int, x2:Int, y2:Int)) == y1 - in r2(x2, update(x1, y1, x2, y2)) == y2 - out r3(x3:Int, update(x1, y1, x2, y2)) == x1 + y1 + x2 + y2 + in r1(x1, update(x1:Int, y1:Int, x2:Int, y2:Int)) = y1 + in r2(x2, update(x1, y1, x2, y2)) = y2 + out r3(x3:Int, update(x1, y1, x2, y2)) = x1 + y1 + x2 + y2 } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Bug.model b/AlgebraicDataflowArchitectureModel/models/Bug.model index f31727b..1ba4f5e 100644 --- a/AlgebraicDataflowArchitectureModel/models/Bug.model +++ b/AlgebraicDataflowArchitectureModel/models/Bug.model @@ -1,7 +1,7 @@ channel CIO{ - out aUa(a, input(x:Int)) == x + out aUa(a, input(x:Int)) = x } channel C1{ - in aUa(a, update(x)) == x - out aUb(b, update(x)) == x + 3 + in aUa(a, update(x)) = x + out aUb(b, update(x)) = x + 3 } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Clock.dtram b/AlgebraicDataflowArchitectureModel/models/Clock.dtram index 939c325..bbeb6dc 100644 --- a/AlgebraicDataflowArchitectureModel/models/Clock.dtram +++ b/AlgebraicDataflowArchitectureModel/models/Clock.dtram @@ -1,18 +1,18 @@ model { channel CIO1 { - out min(m: Int, tick) == mod(m + 1, 60) + out min(m: Int, tick) = (m + 1) % 60 } channel HourUpdate { - in hour(h: Int, update(h2)) == h2 - out hour_ang(h_ang: Double, update(h2)) == h2 / 6 * PI + in hour(h: Int, update(h2)) = h2 + out hour_ang(h_ang: Double, update(h2)) = h2 / 6 * PI } channel MinUpdate { - in min(m, update(m2)) == m2 - out min_ang(m_ang: Double, update(m2)) == m2 / 30 * PI + in min(m, update(m2)) = m2 + out min_ang(m_ang: Double, update(m2)) = m2 / 30 * PI } channel Clock { - in min(m, update(m2)) == m2 - out hour(h, update(m2)) == if(eq(m2, 0), mod(h + 1, 24), h) + in min(m, update(m2)) = m2 + out hour(h, update(m2)) = if(m2 == 0, (h + 1) % 24, h) } } geometry { diff --git a/AlgebraicDataflowArchitectureModel/models/Clock.model b/AlgebraicDataflowArchitectureModel/models/Clock.model index 0cabf0e..0ecb11b 100644 --- a/AlgebraicDataflowArchitectureModel/models/Clock.model +++ b/AlgebraicDataflowArchitectureModel/models/Clock.model @@ -1,15 +1,15 @@ channel CIO1 { - out min(m: Int, tick) == mod(m + 1, 60) + out min(m: Int, tick) = (m + 1) % 60 } channel HourUpdate { - in hour(h: Int, update(h2)) == h2 - out hour_ang(h_ang: Double, update(h2)) == h2 / 6 * PI + in hour(h: Int, update(h2)) = h2 + out hour_ang(h_ang: Double, update(h2)) = h2 / 6 * PI } channel MinUpdate { - in min(m, update(m2)) == m2 - out min_ang(m_ang: Double, update(m2)) == m2 / 30 * PI + in min(m, update(m2)) = m2 + out min_ang(m_ang: Double, update(m2)) = m2 / 30 * PI } channel Clock { - in min(m, update(m2)) == m2 - out hour(h, update(m2)) == if(eq(m2, 0), mod(h + 1, 24), h) + in min(m, update(m2)) = m2 + out hour(h, update(m2)) = if(m2 == 0, (h + 1) % 24, h) } diff --git a/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model b/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model index b3ddeb5..42cdf13 100644 --- a/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model +++ b/AlgebraicDataflowArchitectureModel/models/CustomerOffice.model @@ -1,21 +1,21 @@ channel CIO_AddCustomer { - out customers(db:Map, addCustomer(uid:Str, off:Str)) == insert(db, uid, {"off": off}) + out customers(db:Map, addCustomer(uid:Str, off:Str)) = insert(db, uid, {"off": off}) } channel CIO_AddCampany { - out companies(db:Map, addCampany(cid:Str, add:Str)) == insert(db, cid, {"add": add}) + out companies(db:Map, addCampany(cid:Str, add:Str)) = insert(db, cid, {"add": add}) } channel CIO_SetCustomerOff(uid:Str) { - out customers.{uid}.off(cid:Str, setOff(cid2)) == cid2 + out customers.{uid}.off(cid:Str, setOff(cid2)) = cid2 } channel CIO_SetCompanyAdd(cid:Str) { - out companies.{cid}.add(a1:Str, setAdd(a2)) == a2 + out companies.{cid}.add(a1:Str, setAdd(a2)) = a2 } channel C(uid:Str) { - in customers.{uid}.off(cid, sync(cid2, add2)) == cid2 - in companies.{cid2}.add(a1, sync(cid2, add2)) == add2 - out customers.{uid}.add(a3:Str, sync(cid2, add2)) == add2 + in customers.{uid}.off(cid, sync(cid2, add2)) = cid2 + in companies.{cid2}.add(a1, sync(cid2, add2)) = add2 + out customers.{uid}.add(a3:Str, sync(cid2, add2)) = add2 } diff --git a/AlgebraicDataflowArchitectureModel/models/Game.model b/AlgebraicDataflowArchitectureModel/models/Game.model index bc90ba4..1952ff0 100644 --- a/AlgebraicDataflowArchitectureModel/models/Game.model +++ b/AlgebraicDataflowArchitectureModel/models/Game.model @@ -1,32 +1,32 @@ channel CIO { - out force(f:Double, action(x:Double)) == x - out time(t:Double, action(x)) == t + 0.01 - out force(f, e) == x - out time(t, e) == t + 0.01 + out force(f:Double, action(x:Double)) = x + out time(t:Double, action(x)) = t + 0.01 + out force(f, e) = x + out time(t, e) = t + 0.01 } channel CIO2 { - out velocity(v:Double, setVel(x:Double)) == x - out velocity(v, e) == x + out velocity(v:Double, setVel(x:Double)) = x + out velocity(v, e) = x } channel CIO3 { - out mass(m:Double, setMass(x:Double)) == x - out mass(m, e) == m + out mass(m:Double, setMass(x:Double)) = x + out mass(m, e) = m } channel C1 { - in force(f, update1(y, z)) == y - in mass(m, update1(y, z)) == z - out acceleration(a: Double, update1(y, z)) == y / z + in force(f, update1(y, z)) = y + in mass(m, update1(y, z)) = z + out acceleration(a: Double, update1(y, z)) = y / z } channel C2 { - in acceleration(a, update2(z)) == z - out velocity(v:Double, update2(z)) == v + 0.01 * z + in acceleration(a, update2(z)) = z + out velocity(v:Double, update2(z)) = v + 0.01 * z } channel C3 { - in velocity(v, update3(u)) == u - out position(p:Double, update3(u)) == p + 0.01 * u + in velocity(v, update3(u)) = u + out position(p:Double, update3(u)) = p + 0.01 * u } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Hello.model b/AlgebraicDataflowArchitectureModel/models/Hello.model index 46bb932..38759d7 100644 --- a/AlgebraicDataflowArchitectureModel/models/Hello.model +++ b/AlgebraicDataflowArchitectureModel/models/Hello.model @@ -1,3 +1,3 @@ channel cio { - out r1(x1:Int,set(x2)) == x2 + out r1(x1:Int,set(x2)) = x2 } diff --git a/AlgebraicDataflowArchitectureModel/models/Hello2.model b/AlgebraicDataflowArchitectureModel/models/Hello2.model index 4815cf6..67eb1c0 100644 --- a/AlgebraicDataflowArchitectureModel/models/Hello2.model +++ b/AlgebraicDataflowArchitectureModel/models/Hello2.model @@ -1,3 +1,3 @@ channel cio { - out r1(x1:Int,set(x2:Int)) == x2:Int + out r1(x1:Int,set(x2:Int)) = x2:Int } diff --git a/AlgebraicDataflowArchitectureModel/models/HelloWorld.model b/AlgebraicDataflowArchitectureModel/models/HelloWorld.model index 44aa310..2a5fa1e 100644 --- a/AlgebraicDataflowArchitectureModel/models/HelloWorld.model +++ b/AlgebraicDataflowArchitectureModel/models/HelloWorld.model @@ -1,7 +1,7 @@ channel cio { - out r1(x1:Int,set(x2:Int)) == x2:Int + out r1(x1:Int,set(x2:Int)) = x2:Int } channel c2 { - in r1(x1:Int,update(x2:Int)) == x2:Int - out r2(y1:Int,update(x2:Int)) == (x2:Int+1) + in r1(x1:Int,update(x2:Int)) = x2:Int + out r2(y1:Int,update(x2:Int)) = (x2:Int+1) } diff --git a/AlgebraicDataflowArchitectureModel/models/InventoryManagement.model b/AlgebraicDataflowArchitectureModel/models/InventoryManagement.model new file mode 100644 index 0000000..c41ed3c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/InventoryManagement.model @@ -0,0 +1,7 @@ +channel ItemRegistration { + out inventory(items:Map, registerItem(itemId:Str, quantity:Int)) = insert(items, itemId, {"count": quantity}) +} + +channel ReceivingOrShipping(itemId:Str) { + out inventory.{itemId}.count(prev_quantity:Int, receiveOrship(quantity:Int)) = prev_quantity + quantity +} diff --git a/AlgebraicDataflowArchitectureModel/models/JumpGame.model b/AlgebraicDataflowArchitectureModel/models/JumpGame.model index 1981df9..43b8d0c 100644 --- a/AlgebraicDataflowArchitectureModel/models/JumpGame.model +++ b/AlgebraicDataflowArchitectureModel/models/JumpGame.model @@ -1,7 +1,8 @@ init { force := pair(0.0, 0.0) time := 0.0 - move := pair(0.0, 0.0) + movex := 0.0 + movey := 0.0 mass := 1.0 ground := true acceleration := pair(0.0, 0.0) @@ -12,59 +13,59 @@ gameover := false } channel CIO { - out force(f:Pair, gravity(y:Double)) == pair(0.0, y) - out time(t:Double, gravity(y)) == t + 0.01 + out force(f:Pair, gravity(y:Double)) = pair(0.0, y) + out time(t:Double, gravity(y)) = t + 0.01 } channel CIO2 { - out movex(x:Double, run(x2:Double)) == x2 + out movex(x:Double, run(x2:Double)) = x2 } channel CIO3 { - out movey(y:Double, jump(y2:Double)) == y2 + out movey(y:Double, jump(y2:Double)) = y2 } channel CIO4 { - out mass(m:Double, setMass(x:Double)) == x + out mass(m:Double, setMass(x:Double)) = x } channel CIO5 { - out ground(g:Bool, openHole) == false - out ground(g, closeHole) == true + out ground(g:Bool, openHole) = false + out ground(g, closeHole) = true } channel C1 { ref onground(o, update1(f2, m2, o)) - in force(f, update1(f2, m2, o)) == f2 - in mass(m, update1(f2, m2, o)) == m2 - out acceleration(a:Pair, update1(f2, m2, o)) == if(o, pair(left(f2) / m2, 0.0), pair(left(f2) / m2, right(f2) / m2)) + in force(f, update1(f2, m2, o)) = f2 + in mass(m, update1(f2, m2, o)) = m2 + out acceleration(a:Pair, update1(f2, m2, o)) = if(o, pair(left(f2) / m2, 0.0), pair(left(f2) / m2, right(f2) / m2)) } channel C2 { ref onground(o, update3(a2, o)) - in acceleration(a, update3(a2, o)) == a2 - out velocity(v:Pair, update3(a2, o)) == if(and(o, lt(right(v), 0.0)), + in acceleration(a, update3(a2, o)) = a2 + out velocity(v:Pair, update3(a2, o)) = if(o && right(v) < 0.0, pair(left(v) + 0.01 * left(a2), 0.0), pair(left(v) + 0.01 * left(a2), right(v) + 0.01 * right(a2))) } channel C3 { ref onground(o, update4(x2, o)) - in movex(x, update4(x2, o)) == x2 - out velocity(v:Pair, update4(x2, o)) == if(o, pair(x2, right(v)), v) + in movex(x, update4(x2, o)) = x2 + out velocity(v:Pair, update4(x2, o)) = if(o, pair(x2, right(v)), v) } channel C4 { ref onground(o, update5(x2, o)) - in movey(y, update5(y2, o)) == y2 - out velocity(v:Pair, update5(y2, o)) == if(o, pair(left(v), y2), v) + in movey(y, update5(y2, o)) = y2 + out velocity(v:Pair, update5(y2, o)) = if(o, pair(left(v), y2), v) } channel C5 { - in velocity(v, update6(v2, g)) == v2 + in velocity(v, update6(v2, g)) = v2 ref ground(g, update6(v2, g)) - out position(p:Pair, update6(v2, g)) == if(and(eq(g, true), lt(right(p) + 0.01 * right(v2), 0.0)), + out position(p:Pair, update6(v2, g)) = if(g == true && right(p) + 0.01 * right(v2) > 0.0, pair(left(p) + 0.01 * left(v2), 0.0), pair(left(p) + 0.01 * left(v2), right(p) + 0.01 * right(v2))) } channel C6 { - in position(p, update2(p2, g2)) == p2 - in ground(g, update2(p2, g2)) == g2 - out onground(o:Bool, update2(p2, g2)) == and(eq(g2, true), le(right(p2), 0.0)) + in position(p, update2(p2, g2)) = p2 + in ground(g, update2(p2, g2)) = g2 + out onground(o:Bool, update2(p2, g2)) = (g2 == true && right(p2) <= 0.0) } channel C7 { - in position(p, update7(p2)) == p2 - out clear(c:Bool, update7(p2)) == if(gt(left(p2), 100.0), true, false) - out gameover(go:Bool, update7(p2)) == if(lt(right(p2), -1.0), true, false) + in position(p, update7(p2)) = p2 + out clear(c:Bool, update7(p2)) = (left(p2) > 100.0) + out gameover(go:Bool, update7(p2)) = (right(p2) < -1.0) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Kinematics.model b/AlgebraicDataflowArchitectureModel/models/Kinematics.model new file mode 100644 index 0000000..3d10af4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Kinematics.model @@ -0,0 +1,20 @@ +channel CIO { + out force(f:Double, action(x)) = x + out time(t:Double, action(x)) = t + 0.01 +} + +channel C1 { + in force(f, update1(y, m)) = y + in mass(m, update1(y, m)) = m + out acceleration(a:Double, update1(y, m)) = y / m +} + +channel C2 { + in acceleration(a, update2(z)) = z + out velocity(v:Double, update2(z)) = v + 0.01 * z +} + +channel C3 { + in velocity(v, update3(u)) = u + out position(p:Double, update3(u)) = p + 0.01 * u +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Kinetics.model b/AlgebraicDataflowArchitectureModel/models/Kinetics.model deleted file mode 100644 index 5218206..0000000 --- a/AlgebraicDataflowArchitectureModel/models/Kinetics.model +++ /dev/null @@ -1,20 +0,0 @@ -channel CIO { - out force(f:Double, action(x)) == x - out time(t:Double, action(x)) == t + 0.01 -} - -channel C1 { - in force(f, update1(y, m)) == y - in mass(m, update1(y, m)) == m - out acceleration(a:Double, update1(y, m)) == y / m -} - -channel C2 { - in acceleration(a, update2(z)) == z - out velocity(v:Double, update2(z)) == v + 0.01 * z -} - -channel C3 { - in velocity(v, update3(u)) == u - out position(p:Double, update3(u)) == p + 0.01 * u -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/NemophilaAccounts.model b/AlgebraicDataflowArchitectureModel/models/NemophilaAccounts.model index 37f6b4b..c2cc23a 100644 --- a/AlgebraicDataflowArchitectureModel/models/NemophilaAccounts.model +++ b/AlgebraicDataflowArchitectureModel/models/NemophilaAccounts.model @@ -1,5 +1,5 @@ channel CIO_CreateAccount { - out accounts(acList:List, createAccount(name:Str)) == append(acList, { + out accounts(acList:List, createAccount(name:Str)) = append(acList, { "name": name, "posts": nil, "newFriend": null, @@ -12,75 +12,75 @@ } channel CIO_ChangeName(uid:Str) { - out accounts.{uid}.name(prevName:Str, changeName(name)) == name + out accounts.{uid}.name(prevName:Str, changeName(name)) = name } -channel CIO_CreatePost(uid:Str){ - out accounts.{uid}.posts(postsList:List, createPost(comment:Str)) == cons(comment:Str, postsList) +channel CIO_CreatePost(uid:Str) { + out accounts.{uid}.posts(postsList:List, createPost(comment:Str)) = cons(comment:Str, postsList) } -channel CIO_DeletePost(uid:Str){ - out accounts.{uid}.posts(postsList:List, deletePost(pid:Str)) == remove(postsList, pid:Str) +channel CIO_DeletePost(uid:Str) { + out accounts.{uid}.posts(postsList:List, deletePost(pid:Str)) = remove(postsList, pid:Str) } -channel CIO_PostRequesting(sendId:Str){ - out accounts.{sendId}.newRequesting(preNewResuesting:Str, postRequesting(recvId:Str)) == recvId +channel CIO_PostRequesting(sendId:Str) { + out accounts.{sendId}.newRequesting(preNewResuesting:Str, postRequesting(recvId:Str)) = recvId } -channel C_AddRequesting(sendId:Str){ - in accounts.{sendId}.newRequesting(preNewResuesting:Str, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) == recvId +channel C_AddRequesting(sendId:Str) { + in accounts.{sendId}.newRequesting(preNewResuesting:Str, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) = recvId ref accounts.{sendId}.friends(sendFriends:Map, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) ref accounts.{sendId}.requested(sendRequested:Map, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) ref accounts.{recvId}.requesting(recvRequesting:Map, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) - out accounts.{sendId}.requesting(sendRequesting:Map, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) == if(eq(contains(sendFriends:Map, recvId), true), + out accounts.{sendId}.requesting(sendRequesting:Map, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) = if(contains(sendFriends:Map, recvId) == true, sendRequesting, insert(sendRequesting:Map, recvId:Str, true)) - out accounts.{recvId}.requested(recvRequested:Map, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) == if(eq(contains(sendFriends:Map, recvId), true), + out accounts.{recvId}.requested(recvRequested:Map, sync1(recvId:Str, sendRequested:Map, recvRequesting:Map, sendFriends:Map)) = if(ontains(sendFriends:Map, recvId) == true, recvRequested, insert(recvRequested:Map, sendId:Str, true)) } -channel CIO_RejectRequest(recvId:Str){ - out accounts.{sendId}.requesting(sendRequesting:Map, rejectRequest(sendId:Str)) == delete(sendRequesting:Map, recvId:Str) - out accounts.{recvId}.requested(recvRequested:Map, rejectRequest(sendId:Str)) == delete(recvRequested:Map, sendId:Str) +channel CIO_RejectRequest(recvId:Str) { + out accounts.{sendId}.requesting(sendRequesting:Map, rejectRequest(sendId:Str)) = delete(sendRequesting:Map, recvId:Str) + out accounts.{recvId}.requested(recvRequested:Map, rejectRequest(sendId:Str)) = delete(recvRequested:Map, sendId:Str) } -channel CIO_AdmitFriend(recvId:Str){ - out accounts.{recvId}.newFriend(preNewFriend:Str, admitFriend(sendId:Str)) == sendId +channel CIO_AdmitFriend(recvId:Str) { + out accounts.{recvId}.newFriend(preNewFriend:Str, admitFriend(sendId:Str)) = sendId } -channel C_AddFriend(recvId:Str){ - in accounts.{recvId}.newFriend(preSendId:Str, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) == sendId +channel C_AddFriend(recvId:Str) { + in accounts.{recvId}.newFriend(preSendId:Str, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) = sendId ref accounts.{sendId}.requesting(preSendTing:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) ref accounts.{recvId}.requested(preRecvTed:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) - out accounts.{sendId}.friends(sendFriends:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) == if(and(eq(contains(preSendTing:Map, recvId), true), eq(contains(preRecvTed:Map, sendId), true)), + out accounts.{sendId}.friends(sendFriends:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) = if(contains(preSendTing:Map, recvId) == true && contains(preRecvTed:Map, sendId) == true, insert(sendFriends, recvId:Str, true), sendFriends) - out accounts.{recvId}.friends(recvFriends:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) == if(and(eq(contains(preSendTing:Map, recvId), true), eq(contains(preRecvTed:Map, sendId), true)), + out accounts.{recvId}.friends(recvFriends:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) = if(contains(preSendTing:Map, recvId) == true && contains(preRecvTed:Map, sendId) == true, insert(recvFriends, sendId:Str, true), recvFriends) - out accounts.{sendId}.requesting(sendRequesting:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) == if(and(eq(contains(preSendTing:Map, recvId), true), eq(contains(preRecvTed:Map, sendId), true)), + out accounts.{sendId}.requesting(sendRequesting:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) = if(contains(preSendTing:Map, recvId) == true && contains(preRecvTed:Map, sendId) == true, delete(sendRequesting:Map, recvId:Str), sendRequesting) - out accounts.{recvId}.requested(recvRequested:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) == if(and(eq(contains(preSendTing:Map, recvId), true), eq(contains(preRecvTed:Map, sendId), true)), + out accounts.{recvId}.requested(recvRequested:Map, sync2(sendId:Str, preSendTing:Map, preRecvTed:Map)) = if(contains(preSendTing:Map, recvId) == true && contains(preRecvTed:Map, sendId) == true, delete(recvRequested:Map, sendId:Str), recvRequested) } -channel CIO_DeleteFriendRequest(sendId:Str){ - out accounts.{sendId}.delReqFriend(preDelReqFriend:Str, deleteFriend(recvId:Str)) == recvId +channel CIO_DeleteFriendRequest(sendId:Str) { + out accounts.{sendId}.delReqFriend(preDelReqFriend:Str, deleteFriend(recvId:Str)) = recvId } -channel CIO_DeleteFriend(sendId:Str){ - in accounts.{sendId}.delReqFriend(preRecvId:Str, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) == recvId +channel CIO_DeleteFriend(sendId:Str) { + in accounts.{sendId}.delReqFriend(preRecvId:Str, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) = recvId ref accounts.{sendId}.friends(preSendFriends:Map, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) ref accounts.{recvId}.friends(preRecvFriends:Map, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) - out accounts.{sendId}.friends(sendFriends:Map, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) == if(or(eq(contains(preSendFriends:Map, recvId), true), eq(contains(preRecvFriends:Map, sendId), true)), + out accounts.{sendId}.friends(sendFriends:Map, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) = if(contains(preSendFriends:Map, recvId) == true || contains(preRecvFriends:Map, sendId) == true, delete(sendFriends:Map, recvId:Str), sendFriends) - out accounts.{recvId}.friends(recvFriends:Map, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) == if(or(eq(contains(preSendFriends:Map, recvId), true), eq(contains(preRecvFriends:Map, sendId), true)), + out accounts.{recvId}.friends(recvFriends:Map, sync3(recvId:Str, preSendFriends:Map, preRecvFriends:Map)) = if(contains(preSendFriends:Map, recvId) == true || contains(preRecvFriends:Map, sendId) == true, delete(recvFriends:Map, sendId:Str), recvFriends) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame.model b/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame.model index ceb7100..846ffbf 100644 --- a/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame.model +++ b/AlgebraicDataflowArchitectureModel/models/OnlineBattleGame.model @@ -1,31 +1,31 @@ channel CIO_Signup{ - out accounts(adb:Map, signUp(aid:Str, name:Str)) == insert(adb, aid, {"name": name}) + out accounts(adb:Map, signUp(aid:Str, name:Str)) = insert(adb, aid, {"name": name}) } channel CIO_ChangeName(aid:Str) { - out accounts.{aid}.name(prev_name:Str, changeName(name)) == name + out accounts.{aid}.name(prev_name:Str, changeName(name)) = name } channel CIO_CreateRoom { - out rooms(rdb:Map, createRoom(rid:Str, blue_id:Str, red_id:Str)) == insert(rdb, rid, {"blue_id": blue_id, "red_id": red_id}) + out rooms(rdb:Map, createRoom(rid:Str, blue_id:Str, red_id:Str)) = insert(rdb, rid, {"blue_id": blue_id, "red_id": red_id}) } channel CIO_ChangeRed_id(rid:Str) { - out rooms.{rid}.red_id(prev_red_id:Str, changeRed_id(red_id)) == red_id + out rooms.{rid}.red_id(prev_red_id:Str, changeRed_id(red_id)) = red_id } channel CIO_ChangeBlue_id(rid:Str) { - out rooms.{rid}.blue_id(prev_blue_id:Str, changeBlue_id(blue_id)) == blue_id + out rooms.{rid}.blue_id(prev_blue_id:Str, changeBlue_id(blue_id)) = blue_id } channel C_red(rid:Str) { - in rooms.{rid}.red_id(prev_aid:Str, sync(aid, name)) == aid - in accounts.{aid}.name(prev_name:Str, sync(aid, name)) == name - out rooms.{rid}.red_name(prev_name:Str, sync(aid, name)) == name + in rooms.{rid}.red_id(prev_aid:Str, sync(aid, name)) = aid + in accounts.{aid}.name(prev_name:Str, sync(aid, name)) = name + out rooms.{rid}.red_name(prev_name:Str, sync(aid, name)) = name } channel C_blue(rid:Str) { - in rooms.{rid}.blue_id(prev_aid:Str, sync(aid, name)) == aid - in accounts.{aid}.name(prev_name:Str, sync(aid, name)) == name - out rooms.{rid}.blue_name(prev_name:Str, sync(aid, name)) == name + in rooms.{rid}.blue_id(prev_aid:Str, sync(aid, name)) = aid + in accounts.{aid}.name(prev_name:Str, sync(aid, name)) = name + out rooms.{rid}.blue_name(prev_name:Str, sync(aid, name)) = name } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/POS.dtram b/AlgebraicDataflowArchitectureModel/models/POS.dtram index dc3d2d1..d1cb11c 100644 --- a/AlgebraicDataflowArchitectureModel/models/POS.dtram +++ b/AlgebraicDataflowArchitectureModel/models/POS.dtram @@ -1,18 +1,18 @@ model { channel CIO { - out payment(p:Int, purchase(x:Int)) == x + out payment(p:Int, purchase(x:Int)) = x } channel C3 { - in history(h, update3(u)) == u - out total(t:Int, update3(u)) == sum(u) + in history(h, update3(u)) = u + out total(t:Int, update3(u)) = sum(u) } channel C1 { - in payment(p, update1(y)) == y - out points(l:Int, update1(y)) == floor(y * 0.05) + in payment(p, update1(y)) = y + out points(l:Int, update1(y)) = floor(y * 0.05) } channel C2 { - in payment(p, update2(z)) == z - out history(h:List, update2(z)) == cons(z, h) + in payment(p, update2(z)) = z + out history(h:List, update2(z)) = cons(z, h) } } geometry { diff --git a/AlgebraicDataflowArchitectureModel/models/POS.model b/AlgebraicDataflowArchitectureModel/models/POS.model index 150c106..c15c931 100644 --- a/AlgebraicDataflowArchitectureModel/models/POS.model +++ b/AlgebraicDataflowArchitectureModel/models/POS.model @@ -1,15 +1,15 @@ channel CIO { - out payment(p:Int, purchase(x:Int)) == x + out payment(p:Int, purchase(x:Int)) = x } channel C3 { - in history(h, update3(u)) == u - out total(t:Int, update3(u)) == sum(u) + in history(h, update3(u)) = u + out total(t:Int, update3(u)) = sum(u) } channel C1 { - in payment(p, update1(y)) == y - out points(l:Int, update1(y)) == floor(y * 0.05) + in payment(p, update1(y)) = y + out points(l:Int, update1(y)) = floor(y * 0.05) } channel C2 { - in payment(p, update2(z)) == z - out history(h:List, update2(z)) == cons(z, h) + in payment(p, update2(z)) = z + out history(h:List, update2(z)) = cons(z, h) } diff --git a/AlgebraicDataflowArchitectureModel/models/POS2.model b/AlgebraicDataflowArchitectureModel/models/POS2.model index 6ae676d..0ee31d2 100644 --- a/AlgebraicDataflowArchitectureModel/models/POS2.model +++ b/AlgebraicDataflowArchitectureModel/models/POS2.model @@ -1,14 +1,14 @@ channel CIO { - out payment(p:Int, purchase(x:Int)) == x + out payment(p:Int, purchase(x:Int)) = x } channel C1 { - in payment(p1, update1(y)) == y - out points(l:Int, update1(y)) == floor(y * 0.05) + in payment(p1, update1(y)) = y + out points(l:Int, update1(y)) = floor(y * 0.05) } channel C2 { - in payment(p1, update2(z)) == z - out history(h:List, update2(z)) == cons(z, h) - out total(t:Int, update2(z)) == z + t + in payment(p1, update2(z)) = z + out history(h:List, update2(z)) = cons(z, h) + out total(t:Int, update2(z)) = z + t } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/SimpleTwitter.model b/AlgebraicDataflowArchitectureModel/models/SimpleTwitter.model new file mode 100644 index 0000000..cea527d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/SimpleTwitter.model @@ -0,0 +1,7 @@ +channel Signup{ + out accounts(accountMap:Map, signUp(accountId:Str, name:Str)) = insert(accountMap, accountId, {"name": name, "tweets": nil}) +} + +channel Tweet(accountId:Str) { + out accounts.{accountId}.tweets(tweetList:List, tweet(contents:Str)) = append(tweetList, contents) +} diff --git a/AlgebraicDataflowArchitectureModel/models/StockManagement.model b/AlgebraicDataflowArchitectureModel/models/StockManagement.model index b133f44..4528cb7 100644 --- a/AlgebraicDataflowArchitectureModel/models/StockManagement.model +++ b/AlgebraicDataflowArchitectureModel/models/StockManagement.model @@ -4,47 +4,47 @@ } channel CIO_enter { - out arrival(s:Tuple, arrive(item:Str, num:Int)) == tuple(item, num) + out arrival(s:Tuple, arrive(item:Str, num:Int)) = tuple(item, num) } channel CIO_req { - out request(r:Tuple, req(item:Str, num:Int)) == tuple(item, num) + out request(r:Tuple, req(item:Str, num:Int)) = tuple(item, num) } channel C1 { - in arrival(ar, update1(ar2, st)) == ar2 + in arrival(ar, update1(ar2, st)) = ar2 ref stock(st:Map, update1(ar2, st)) - out available(av:Tuple, update1(ar2, st)) == tuple(fst(ar2), snd(ar2) + lookup(st, fst(ar2))) + out available(av:Tuple, update1(ar2, st)) = tuple(fst(ar2), snd(ar2) + lookup(st, fst(ar2))) } channel C2 { - in available(av, update2(av2, sh)) == av2 + in available(av, update2(av2, sh)) = av2 ref shortage(sh, update2(av2, sh)) - out deriver(dr:Tuple, update2(av2, sh)) == if(ge(snd(av2), lookup(sh, fst(av2))), + out deriver(dr:Tuple, update2(av2, sh)) = if(snd(av2) >= lookup(sh, fst(av2)), tuple(fst(av2), lookup(sh, fst(av2)), snd(av2) - lookup(sh, fst(av2))), tuple(fst(av2), 0, snd(av2))) - out shortage(s, update2(av2, sh)) == if(ge(snd(av2), lookup(s, fst(av2))), + out shortage(s, update2(av2, sh)) = if(snd(av2) >= lookup(s, fst(av2)), insert(s, fst(av2), 0), s) } channel C3 { - in deriver(dr, update3(dr2)) == dr2 - out stock(st, update3(dr2)) == insert(st, fst(dr2), snd(snd(dr2))) + in deriver(dr, update3(dr2)) = dr2 + out stock(st, update3(dr2)) = insert(st, fst(dr2), snd(snd(dr2))) } channel C4 { - in deriver(dr, update4(dr2)) == dr2 - out shipping(sp:Tuple, update4(dr2)) == tuple(fst(dr2), fst(snd(dr2))) + in deriver(dr, update4(dr2)) = dr2 + out shipping(sp:Tuple, update4(dr2)) = tuple(fst(dr2), fst(snd(dr2))) } channel C5 { - in request(rq, update5(rq2, st)) == rq2 + in request(rq, update5(rq2, st)) = rq2 ref stock(st, update5(rq2, st)) - out deriver(dr, update5(rq2, st)) == if(ge(lookup(st, fst(rq2)), snd(rq2)), + out deriver(dr, update5(rq2, st)) = if(lookup(st, fst(rq2)) >= snd(rq2), tuple(fst(rq2), snd(rq2), lookup(st, fst(rq2)) - snd(rq2)), tuple(fst(rq2), 0, lookup(st, fst(rq2)))) - out shortage(sh, update5(rq2, st)) == if(ge(lookup(st, fst(rq2)), snd(rq2)), + out shortage(sh, update5(rq2, st)) = if(lookup(st, fst(rq2)) >= snd(rq2), sh, insert(sh, fst(rq2), lookup(sh, fst(rq2)) + snd(rq2))) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/StockManagement2.model b/AlgebraicDataflowArchitectureModel/models/StockManagement2.model index 6ee866a..36d6966 100644 --- a/AlgebraicDataflowArchitectureModel/models/StockManagement2.model +++ b/AlgebraicDataflowArchitectureModel/models/StockManagement2.model @@ -4,10 +4,10 @@ } channel CIO_enter { - out deriver(s:Tuple, arrive(item:Str, num:Int)) == tuple(item, num, num) + out deriver(s:Tuple, arrive(item:Str, num:Int)) = tuple(item, num, num) } channel C3 { - in deriver(dr, update3(dr2)) == dr2 - out shipping(sp:Tuple, update3(dr2)) == tuple(fst(dr2), fst(snd(dr2))) + in deriver(dr, update3(dr2)) = dr2 + out shipping(sp:Tuple, update3(dr2)) = tuple(fst(dr2), fst(snd(dr2))) } diff --git a/AlgebraicDataflowArchitectureModel/models/Test.model b/AlgebraicDataflowArchitectureModel/models/Test.model index a8a1348..0a7daa8 100644 --- a/AlgebraicDataflowArchitectureModel/models/Test.model +++ b/AlgebraicDataflowArchitectureModel/models/Test.model @@ -1,9 +1,9 @@ channel CIO { - out a(x:Int, set(n:Int)) == n + out a(x:Int, set(n:Int)) = n } channel C1 { - in a(x, update(y)) == y - out b(z, update(y)) == y + 1 - out c(v, update(y)) == v + y + in a(x, update(y)) = y + out b(z, update(y)) = y + 1 + out c(v, update(y)) = v + y } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/TravelDistance.model b/AlgebraicDataflowArchitectureModel/models/TravelDistance.model index a0c8fe2..07d12db 100644 --- a/AlgebraicDataflowArchitectureModel/models/TravelDistance.model +++ b/AlgebraicDataflowArchitectureModel/models/TravelDistance.model @@ -1,13 +1,13 @@ channel CX { - out pos_x(prev_x: Double, setX(cur_x: Double)) == cur_x + out pos_x(prev_x: Double, setX(cur_x: Double)) = cur_x } channel CY { - out pos_y(prev_y: Double, setY(cur_y: Double)) == cur_y + out pos_y(prev_y: Double, setY(cur_y: Double)) = cur_y } channel C { - in pos_x(prev_x, move(dx, dy)) == prev_x + dx - in pos_y(prev_y, move(dx, dy)) == prev_y + dy - out dist(prev_d, move(dx, dy)) == prev_d + sqrt(dx * dx + dy * dy) + in pos_x(prev_x, move(dx, dy)) = prev_x + dx + in pos_y(prev_y, move(dx, dy)) = prev_y + dy + out dist(prev_d, move(dx, dy)) = prev_d + sqrt(dx * dx + dy * dy) } diff --git a/AlgebraicDataflowArchitectureModel/models/Triangle.model b/AlgebraicDataflowArchitectureModel/models/Triangle.model index ebfe6b4..cf3d0e0 100644 --- a/AlgebraicDataflowArchitectureModel/models/Triangle.model +++ b/AlgebraicDataflowArchitectureModel/models/Triangle.model @@ -1,13 +1,13 @@ channel cio1 { - out base(x: Double, setBase(x2)) == x2 + out base(x: Double, setBase(x2)) = x2 } channel cio2 { - out height(y: Double, setHeight(y2)) == y2 + out height(y: Double, setHeight(y2)) = y2 } channel triangle { - in base(x, update(x2, y2)) == x2 - in height(y, update(x2, y2)) == y2 - out hypothenuse(z: Double, update(x2, y2)) == sqrt(x2 * x2 + y2 * y2) + in base(x, update(x2, y2)) = x2 + in height(y, update(x2, y2)) = y2 + out hypothenuse(z: Double, update(x2, y2)) = sqrt(x2 * x2 + y2 * y2) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Triangle2.model b/AlgebraicDataflowArchitectureModel/models/Triangle2.model index 82c59bd..5067fa0 100644 --- a/AlgebraicDataflowArchitectureModel/models/Triangle2.model +++ b/AlgebraicDataflowArchitectureModel/models/Triangle2.model @@ -1,13 +1,13 @@ channel cio1 { - out base(x: Double, setBase(x2)) == x2 + out base(x: Double, setBase(x2)) = x2 } channel cio2 { - out height(y: Double, setHeight(y2)) == y2 + out height(y: Double, setHeight(y2)) = y2 } channel triangle { - in base(x, update: Tuple) == fst(update) - in height(y, update) == snd(update) - out hypothenuse(z: Double, update) == sqrt(fst(update) * fst(update) + snd(update) * snd(update)) + in base(x, update: Tuple) = fst(update) + in height(y, update) = snd(update) + out hypothenuse(z: Double, update) = sqrt(fst(update) * fst(update) + snd(update) * snd(update)) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/Twitter.model b/AlgebraicDataflowArchitectureModel/models/Twitter.model index 649abac..491d904 100644 --- a/AlgebraicDataflowArchitectureModel/models/Twitter.model +++ b/AlgebraicDataflowArchitectureModel/models/Twitter.model @@ -1,16 +1,16 @@ channel CIO1(myId:Str) { - out accounts(ac:List, signup(name:Str)) == cons(tuple(name, nil, nil), t1) + out accounts(ac:List, signup(name:Str)) = cons(tuple(name, nil, nil), t1) } channel CIO2(id:Str) { - out accounts.{id}.tweets(t1:List, tweet(text:Str, time:Long)) == cons(tuple(time, text), t1) + out accounts.{id}.tweets(t1:List, tweet(text:Str, time:Long)) = cons(tuple(time, text), t1) } channel C(myId:Str; m:Json) { - in accounts.{myId}.tweets(t1:List, m) == m.myTweets + in accounts.{myId}.tweets(t1:List, m) = m.myTweets sub C2(no:Int; flw:Json := m.followees.{no}) { - in accounts.{myId}.followees.{no}(id:Str, flw) == flw.id - in accounts.{flw.id}.tweets(t2:List, flw) == flw.tweets + in accounts.{myId}.followees.{no}(id:Str, flw) = flw.id + in accounts.{flw.id}.tweets(t2:List, flw) = flw.tweets } - out accounts.{myId}.timeline(l:List, m) == merge(m.myTweets, m.followees) + out accounts.{myId}.timeline(l:List, m) = merge(m.myTweets, m.followees) } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/models/WOS.dtram b/AlgebraicDataflowArchitectureModel/models/WOS.dtram index 45f640c..81b0779 100644 --- a/AlgebraicDataflowArchitectureModel/models/WOS.dtram +++ b/AlgebraicDataflowArchitectureModel/models/WOS.dtram @@ -1,17 +1,17 @@ model { channel CIO2 { - out highest(h:Double, reset(v)) == v + out highest(h:Double, reset(v)) = v } channel CIO1 { - out temp_f(p:Double, observe(x)) == x + out temp_f(p:Double, observe(x)) = x } channel C1{ - in temp_f(q:Double, conversion(y)) == y - out temp_c(r:Double, conversion(z)) == (z-32) / 1.8 + in temp_f(q:Double, conversion(y)) = y + out temp_c(r:Double, conversion(z)) = (z-32) / 1.8 } channel C2{ - in temp_f(q:Double, update(y)) == y - out highest(h:Double, update(z)) == if(gt(z, h), z, h) + in temp_f(q:Double, update(y)) = y + out highest(h:Double, update(z)) = if(z >= h, z, h) } } geometry { diff --git a/AlgebraicDataflowArchitectureModel/models/WeatherObservationSystem.model b/AlgebraicDataflowArchitectureModel/models/WeatherObservationSystem.model index 2cd84d7..0096407 100644 --- a/AlgebraicDataflowArchitectureModel/models/WeatherObservationSystem.model +++ b/AlgebraicDataflowArchitectureModel/models/WeatherObservationSystem.model @@ -1,14 +1,14 @@ channel CIO2 { - out highest(h:Double, reset(v)) == v + out highest(h:Double, reset(v)) = v } channel CIO1 { - out temp_f(p:Double, observe(x)) == x + out temp_f(p:Double, observe(x)) = x } channel C1{ - in temp_f(q:Double, conversion(y)) == y - out temp_c(r:Double, conversion(z)) == (z-32) / 1.8 + in temp_f(q:Double, conversion(y)) = y + out temp_c(r:Double, conversion(z)) = (z-32) / 1.8 } channel C2{ - in temp_f(q:Double, update(y)) == y - out highest(h:Double, update(z)) == if(gt(z, h), z, h) + in temp_f(q:Double, update(y)) = y + out highest(h:Double, update(z)) = if(z >= h, z, h) } diff --git a/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java b/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java index 38e2370..1835abf 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java +++ b/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java @@ -17,6 +17,7 @@ import application.actions.OpenAction; import application.actions.SaveAction; import application.actions.SaveAsAction; +import application.actions.SimulateAction; import application.actions.TreeLayoutAction; import application.actions.ZoomInAction; import application.actions.ZoomOutAction; @@ -37,6 +38,8 @@ private DAGLayoutAction dagLayoutAction = null; private TreeLayoutAction treeLayoutAction = null; private CircleLayoutAction circleLayoutAction = null; + //private SimulateAction simulateAction = null; + public ApplicationMenuBar(ApplicationWindow applicationWindow) { this.applicationWindow = applicationWindow; @@ -72,6 +75,9 @@ menu.add(new ZoomInAction(applicationWindow.getGraphComponent())); menu.add(new ZoomOutAction(applicationWindow.getGraphComponent())); + menu = add(new JMenu("Simulate")); + menu.add(new SimulateAction(applicationWindow)); + menu = add(new JMenu("Generate")); menu.add(javaPrototypeGenerateAction = new JavaPrototypeGenerateAction(applicationWindow.getEditor())); menu.add(jerseyPrototypeGenerateAction = new JerseyPrototypeGenerateAction(applicationWindow.getEditor())); diff --git a/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java b/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java new file mode 100644 index 0000000..37aeefe --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java @@ -0,0 +1,195 @@ +package application; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.swing.JFrame; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.handler.mxRubberband; +import com.mxgraph.util.mxEvent; +import com.mxgraph.util.mxEventObject; +import com.mxgraph.util.mxPoint; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.view.mxGraph; + +import application.actions.SimulateAction; +import application.editor.DataTransferModelingCellEditor; +import application.editor.Editor; +import application.editor.InputEventCellEditor; +import application.layouts.DAGLayout; +import generators.JavaCodeGenerator; +import models.Edge; +import models.EdgeAttribute; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.ChannelNode; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.ResourceNode; +import parser.Parser; +import parser.ParserDTRAM; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import parser.Parser.TokenStream; +import simulator.Event; +import simulator.Resource; +import simulator.ResourceIdentifier; +import simulator.Simulator; + +public class SimulatorWindow extends JFrame{ + + /** + * + */ + private static final long serialVersionUID = -2425820512017088254L; + public static final String title = "Simulation Tool"; + + final int PORT_DIAMETER = 8; + final int PORT_RADIUS = PORT_DIAMETER / 2; + + private Editor editor = null; + private mxGraph graph = null; + private mxGraphComponent graphComponent = null; + private Simulator simulator = null; + private boolean bReflectingArchitectureModel = false; + private double x = 20; + private double y = 20; + + public SimulatorWindow(Editor editor) { + setTitle(title); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + this.graph = new mxGraph() { + public boolean isPort(Object cell) { + mxGeometry geo = getCellGeometry(cell); + + return (geo != null) ? geo.isRelative() : false; + } + + public boolean isCellFoldable(Object cell, boolean collapse) { + return false; + } + }; + + this.graphComponent = new mxGraphComponent(graph); + this.editor = editor; + + graph.getModel().addListener(mxEvent.CHANGE, new mxIEventListener() { + public void invoke(Object sender, mxEventObject evt) { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change: ((List) evt.getProperties().get("changes"))) { + if (change instanceof mxGraphModel.mxTerminalChange) { + mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + if (terminals.size() == 2) { + if (!editor.connectEdge(cell, terminals.get(0), terminals.get(1))) { + graph.removeCells(new mxCell[] {cell}); + } + } + } + }); + getContentPane().add(graphComponent); + new mxRubberband(graphComponent); + graph.setAllowDanglingEdges(false); + graph.setCellsDisconnectable(true); + + setTitle(title); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setSize(870,640); + setVisible(true); + + simulator = new Simulator(this.editor.getModel()); + constructSimulateGraph(simulator.getCurState().getRootResources(), this.editor.getModel(),this.editor.getDataFlowGraph()); + graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); + } + + + public mxGraph constructSimulateGraph(Set simulateRes, DataTransferModel model, DataFlowGraph dataFlowGraph) { + bReflectingArchitectureModel = true; + ((mxGraphModel) graph.getModel()).clear(); + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + + try { + Map resources = new HashMap<>(); + + // create resource vertices + for (Resource resNode: simulateRes) { + int w = 80; + int h = 30; + ResourcePath res = resNode.getResourceIdentifier(); + Object resource = graph.insertVertex(parent, null, + res.toString(), x, y, w, h, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(resNode, resource); + createChildSimulateResourceVerticies(resource, resNode, resources, w, h); + x+=80; + } + + } finally { + graph.getModel().endUpdate(); + } + + bReflectingArchitectureModel = false; + return graph; + } + + + public void createChildSimulateResourceVerticies(Object resource, Resource resNode, Map resources, int w, int h) { //sample + + if(resNode.getChildren() != null) { + for (Resource childNode: resNode.getChildren()) { + ResourcePath childRes = childNode.getResourceIdentifier(); + Object childResource = graph.insertVertex(resource, null, + childRes.toString(), 0, 0, w/2, h/2, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(childNode, childResource); + createChildSimulateResourceVerticies(childResource, childNode, resources, w, h); + } + } + if (resNode.getChildren() == null || resNode.getChildren().size() == 0) { + Object state = graph.insertVertex(resource, null, + resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex + } + } + + public mxGraphComponent getGraphComponent() { + return graphComponent; + } + + public Editor getEditor() { + return editor; + } + + public void setEditor(Editor editor) { + this.editor = editor; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/SimulateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/SimulateAction.java new file mode 100644 index 0000000..9f0e5a2 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/SimulateAction.java @@ -0,0 +1,38 @@ +package application.actions; + +import java.awt.event.ActionEvent; +import java.io.File; + +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; + +import application.ApplicationWindow; +import application.SimulatorWindow; +import application.editor.Editor; +import models.dataFlowModel.DataTransferChannel; + +public class SimulateAction extends AbstractSystemAction { + + private SimulatorWindow simulatorWindow = null; + + /** + * + */ + private static final long serialVersionUID = -995609232489316795L; + + public SimulateAction(ApplicationWindow frame) { + super("Simulate", frame); + //this.simulatorWindow = new SimulatorWindow(frame.getEditor()); + } + + + @Override + public void actionPerformed(ActionEvent e) { + this.simulatorWindow = new SimulatorWindow(frame.getEditor()); + } + +} + diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 3ea8a48..18960d8 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -337,7 +337,7 @@ } for (ResourcePath res: model.getResourcePaths()){ - if(res instanceof ResourcePath && state.getLabel().equals(res.getResourceName())) + if(res instanceof ResourcePath && state.getLabel().equals(res.getLeafResourceName())) fileString += "\tnode r " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; } @@ -383,7 +383,7 @@ int h = 30; ResourcePath res = resNode.getPrimaryResourcePath(); Object resource = graph.insertVertex(parent, null, - res.getResourceName(), 20, 20, w, h, + res.getLeafResourceName(), 20, 20, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex resources.put(resNode, resource); createChildResourceVerticies(resource, resNode, resources, w, h); diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java new file mode 100644 index 0000000..bad12b2 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java @@ -0,0 +1,330 @@ +package application.editor; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.util.EventObject; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.model.mxIGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.view.mxICellEditor; +import com.mxgraph.util.mxConstants; +import com.mxgraph.util.mxUtils; +import com.mxgraph.view.mxCellState; +import com.mxgraph.view.mxGraph; +import com.mxgraph.view.mxGraphView; + +import application.SimulatorWindow; +import application.layouts.DAGLayout; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.visualModel.FormulaChannel; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import simulator.ChannelState; +import simulator.Resource; +import simulator.ResourceIdentifier; +import simulator.Simulator; +import simulator.Event; +import simulator.SystemState; + +public class InputEventCellEditor implements mxICellEditor { + public int DEFAULT_MIN_WIDTH = 70; + public int DEFAULT_MIN_HEIGHT = 30; + public double DEFAULT_MINIMUM_EDITOR_SCALE = 1; + private double x = 20; + private double y = 20; + + protected double minimumEditorScale = DEFAULT_MINIMUM_EDITOR_SCALE; + protected int minimumWidth = DEFAULT_MIN_WIDTH; + protected int minimumHeight = DEFAULT_MIN_HEIGHT; + + private Object editingCell; + private EventObject trigger; + private JComboBox comboBox; + private mxGraphComponent graphComponent; + private Simulator simulator; + private JComboBox pulldownMenu; + private Editor editor; + private boolean bReflectingArchitectureModel = false; + private mxGraph graph; + + public InputEventCellEditor(mxGraphComponent graphComponent, Simulator simulator, Editor editor, mxGraph graph) { + this.graphComponent = graphComponent; + this.simulator = simulator; + this.editor = editor; + this.graph = graph; + } + + @Override + public Object getEditingCell() { + return editingCell; + } + + @Override + public void startEditing(Object cell, EventObject evt) { + if (editingCell != null) { + stopEditing(true); + } + if (!graphComponent.getGraph().getModel().isEdge(cell)) { + + Resource res = simulator.getCurState().getResource((String) ((mxCell) cell).getValue()); + ResourceIdentifier resId = res.getResourceIdentifier();//resource + ArrayList eventChs = new ArrayList<>();//iOchannelList + ArrayList messages = new ArrayList<>();//ADLmessage + ArrayList eventMessages = new ArrayList<>();//messageList + ResourcePath eventResPath = null; + + for(Channel ch : simulator.getModel().getIOChannels()) {//all channel + if(((DataTransferChannel)ch).getInputResources().size()== 0) {//ioch Or normalch + for(ChannelMember out: ((DataTransferChannel)ch).getOutputChannelMembers()) { + ResourcePath resPath = out.getResource(); + if(resId.isInstanceOf(resPath)) {//account.uid == acounts.123 + eventResPath = resPath; + eventChs.add(((DataTransferChannel)ch)); + String message = null; + Expression mesExp = out.getStateTransition().getMessageExpression();//sync(a,b) + eventMessages.add(mesExp); + if(mesExp instanceof Term) { + message = ((Term) mesExp).getSymbol().toString();//sync + }else if(mesExp instanceof Variable) { + message = ((Variable) mesExp).getName();//x,y,z.. + } + messages.add(message);//pulldown + + } + } + } + } + + if(messages.isEmpty()) { + return; + } + String[] eventList = messages.toArray(new String[messages.size()]); + JComboBox event = new JComboBox(eventList); + + JPanel eventChoice = new JPanel(); + eventChoice.add(event);//FirstEventChoice + + int ret = JOptionPane.showConfirmDialog(null, eventChoice, "Event Choice", JOptionPane.OK_CANCEL_OPTION); + if (ret == JOptionPane.OK_OPTION) { + + JPanel inputEvent = new JPanel(); + JTextArea textArea = new JTextArea(eventMessages.get(0).toString(), 10, 30);//EventInput + inputEvent.add(textArea); + + int approve = JOptionPane.showConfirmDialog(null, inputEvent, "Event Code", JOptionPane.OK_CANCEL_OPTION); + if (approve == JOptionPane.OK_OPTION) { + try { + + TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + stream.addLine(textArea.getText()); + Expression eventMessage = parser.parseTerm(stream,simulator.getModel()); + + Event newEvent = new Event(eventChs.get(0), eventMessage, eventResPath, simulator.getCurState().getResource(resId)); + simulator.transition(newEvent); + + constructNextSimulateGraph(simulator.getCurState().getRootResources(), simulator.getModel(),simulator.getModel().getDataFlowGraph(), graph); + graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); + + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined | ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } + } + //resource + return; + } + + mxCellState state = graphComponent.getGraph().getView().getState(cell); + if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { + editingCell = cell; + trigger = evt; + + double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); + Object value = graphComponent.getGraph().getModel().getValue(cell); + if (value != null && value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + comboBox = new JComboBox<>(attr.getOptionStrings()); + comboBox.setBorder(BorderFactory.createEmptyBorder()); + comboBox.setOpaque(false); + comboBox.setBounds(getEditorBounds(state, scale)); + comboBox.setVisible(true); + graphComponent.getGraphControl().add(comboBox, 0); + comboBox.updateUI(); + } + } + } + + private mxGraph constructNextSimulateGraph(Set simulateRes, DataTransferModel model,DataFlowGraph dataFlowGraph, mxGraph nextGraph) { + bReflectingArchitectureModel = true; + ((mxGraphModel) nextGraph.getModel()).clear(); + Object parent = nextGraph.getDefaultParent(); + nextGraph.getModel().beginUpdate(); + + try { + Map resources = new HashMap<>(); + + // create resource vertices + for (Resource resNode: simulateRes) { + int w = 400; + int h = 150; + ResourcePath res = resNode.getResourceIdentifier(); + Object resource = nextGraph.insertVertex(parent, null, + res.toString(), x, y, w, h, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(resNode, resource); + + createNextChildSimulateResourceVerticies(resource, resNode, resources, w, h); + x+=400; + } + + } finally { + nextGraph.getModel().endUpdate(); + } + + bReflectingArchitectureModel = false; + return nextGraph; + } + + private void createNextChildSimulateResourceVerticies(Object resource, Resource resNode, Map resources, int w, int h) { //sample + + if(resNode.getChildren() != null) { + for (Resource childNode: resNode.getChildren()) { + int i = 1; + ResourcePath childRes = childNode.getResourceIdentifier(); + Object childResource = graph.insertVertex(resource, null, + childRes.toString(), x/i, y, w/(i+1), h/(i+2), + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(childNode, childResource); + i++; + createNextChildSimulateResourceVerticies(childResource, childNode, resources, w, h); + } + } + if (resNode.getChildren() == null || resNode.getChildren().size() == 0) { + Object state = graph.insertVertex(resource, null, + resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex + } + } + + @Override + public void stopEditing(boolean cancel) { + if (editingCell != null) { + comboBox.transferFocusUpCycle(); + Object cell = editingCell; + editingCell = null; + if (!cancel) { + EventObject trig = trigger; + trigger = null; + Object value = graphComponent.getGraph().getModel().getValue(cell); + if (value != null && value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + List options = attr.getOptions(); + PushPullValue selected = null; + for (PushPullValue option: options) { + if (option.toString().equals(getCurrentValue())) { + selected = option; + break; + } + } + if (selected != null) { + options.remove(selected); + options.add(0, selected); + } + graphComponent.labelChanged(cell, attr, trig); + } + } else { + mxCellState state = graphComponent.getGraph().getView().getState(cell); + graphComponent.redraw(state); + } + + if (comboBox.getParent() != null) { + comboBox.setVisible(false); + comboBox.getParent().remove(comboBox); + } + + graphComponent.requestFocusInWindow(); + } + } + + public String getCurrentValue() { + return (String) comboBox.getSelectedItem(); + } + + /** + * Returns the bounds to be used for the editor. + */ + public Rectangle getEditorBounds(mxCellState state, double scale) { + mxIGraphModel model = state.getView().getGraph().getModel(); + Rectangle bounds = null; + + bounds = state.getLabelBounds().getRectangle(); + bounds.height += 10; + + // Applies the horizontal and vertical label positions + if (model.isVertex(state.getCell())) { + String horizontal = mxUtils.getString(state.getStyle(), mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); + + if (horizontal.equals(mxConstants.ALIGN_LEFT)) { + bounds.x -= state.getWidth(); + } else if (horizontal.equals(mxConstants.ALIGN_RIGHT)) { + bounds.x += state.getWidth(); + } + + String vertical = mxUtils.getString(state.getStyle(), + mxConstants.STYLE_VERTICAL_LABEL_POSITION, + mxConstants.ALIGN_MIDDLE); + + if (vertical.equals(mxConstants.ALIGN_TOP)) { + bounds.y -= state.getHeight(); + } else if (vertical.equals(mxConstants.ALIGN_BOTTOM)) { + bounds.y += state.getHeight(); + } + } + + bounds.setSize( + (int) Math.max(bounds.getWidth(), + Math.round(minimumWidth * scale)), + (int) Math.max(bounds.getHeight(), + Math.round(minimumHeight * scale))); + + return bounds; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java index 7ced584..bf59db4 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java +++ b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java @@ -68,7 +68,7 @@ public void execute(Object parent) { graphModel.beginUpdate(); try { - // モデルからresource, channel, eventChannelに分ける + // 繝「繝�繝ォ縺九iresource, channel, eventChannel縺ォ蛻�縺代k for (int i = 0; i < graphModel.getChildCount(parent); i++) { mxCell cell = (mxCell) graphModel.getChildAt(parent, i); @@ -76,7 +76,7 @@ mxCellState state = view.getState(cell); cells.add(cell); - // cellがresourceである + // cell縺罫esource縺ァ縺ゅk if ("ellipse".equals(state.getStyle().get("shape"))) { roots.add(cell); hierarchicalRecursionOrder.put(cell, new ArrayList<>()); @@ -88,7 +88,7 @@ continue; } - // cellがeventChannelであるか判定 + // cell縺憩ventChannel縺ァ縺ゅk縺句愛螳� boolean bEventChannel = true; for (int j = 0; j < cell.getEdgeCount(); j++) { mxCell edge = (mxCell) cell.getEdgeAt(j); @@ -97,10 +97,10 @@ } } - // cellがeventChannelである + // cell縺憩ventChannel縺ァ縺ゅk if (bEventChannel) { eventChannels.add(cell); - // cellがchannelである + // cell縺慶hannel縺ァ縺ゅk } else { channels.add(cell); } @@ -109,7 +109,7 @@ } } - // 全てのcellの座標、大きさなどを初期化 + // 蜈ィ縺ヲ縺ョcell縺ョ蠎ァ讓吶�∝、ァ縺阪&縺ェ縺ゥ繧貞�晄悄蛹� for (mxCell c : cells) { c.getGeometry().setX(0); c.getGeometry().setY(0); @@ -121,22 +121,22 @@ } } - // dotEdgesを初期化 + // dotEdges繧貞�晄悄蛹� for (mxCell c : cells) { dotEdges.put(c, new HashSet<>()); } - // lineを構築する + // line繧呈ァ狗ッ峨☆繧� for (mxCell ec : eventChannels) { List newline = new ArrayList(); lines.add(newline); constructionLine(ec, 0); } - // cellの距離を再計算 + // cell縺ョ霍晞屬繧貞�崎ィ育ョ� reculcDist(); - // cellが属するlineのindexを求める + // cell縺悟ア槭☆繧詰ine縺ョindex繧呈アゅa繧� for (int i = 0; i < lines.size(); i++) { for (mxCell cell : lines.get(i)) { if (cellToLineIndex.get(cell) == null) { @@ -146,18 +146,18 @@ } } - // 並べるlineの順番をソートする + // 荳ヲ縺ケ繧詰ine縺ョ鬆�逡ェ繧偵た繝シ繝医☆繧� sortLines(); - Boolean isVersion1 = false; + Boolean isVersion1 = true; System.out.println(vertexToDist); - // cellを配置する + // cell繧帝�咲スョ縺吶k if (isVersion1) { - // channelの所定の位置が階層構造内部になるとき、下にずらして配置するレイアウト + // channel縺ョ謇�螳壹�ョ菴咲スョ縺碁嚴螻、讒矩��蜀�驛ィ縺ォ縺ェ繧九→縺阪�∽ク九↓縺壹i縺励※驟咲スョ縺吶k繝ャ繧、繧「繧ヲ繝� layout1((mxCell) parent); } else { - // channelを階層構造内部でも所定の位置に配置するレイアウト + // channel繧帝嚴螻、讒矩��蜀�驛ィ縺ァ繧よ園螳壹�ョ菴咲スョ縺ォ驟咲スョ縺吶k繝ャ繧、繧「繧ヲ繝� layout2((mxCell) parent); } } finally { @@ -165,7 +165,7 @@ } } - // 階層構造を再帰的に探索 + // 髫主ア、讒矩��繧貞�榊クー逧�縺ォ謗「邏「 public void familySearch(mxCell r, mxCell p, int d) { int childNum = graphModel.getChildCount(p); @@ -183,13 +183,13 @@ } } - // lineを構築する + // line繧呈ァ狗ッ峨☆繧� public void constructionLine(mxCell cur, int d) { - // vertexToDist{key : cell, value : [距離の最小値, 距離の最大値]} を初期化 + // vertexToDist{key : cell, value : [霍晞屬縺ョ譛�蟆丞�、, 霍晞屬縺ョ譛�螟ァ蛟、]} 繧貞�晄悄蛹� if (vertexToDist.get(cur) == null) { vertexToDist.put(cur, Arrays.asList(d, d)); } else { - // 自身が含まれるlineの中で一番大きい距離を保存 + // 閾ェ霄ォ縺悟性縺セ繧後kline縺ョ荳ュ縺ァ荳�逡ェ螟ァ縺阪>霍晞屬繧剃ソ晏ュ� List dists = vertexToDist.get(cur); dists.set(0, Math.max(dists.get(0), d)); dists.set(1, dists.get(0)); @@ -197,30 +197,30 @@ lines.get(lines.size() - 1).add(cur); - int tagCount = 0; // edgeの始点となるcellとして参照された回数 + int tagCount = 0; // edge縺ョ蟋狗せ縺ィ縺ェ繧議ell縺ィ縺励※蜿ら�ァ縺輔l縺溷屓謨ー for (int i = 0; i < cur.getEdgeCount(); i++) { mxCell edge = (mxCell) cur.getEdgeAt(i); mxCellState state = view.getState(edge); mxCell target = (mxCell) edge.getTarget(); - // curが始点となるedgeの終点となるtargetが自身、もしくは存在しない場合を除く + // cur縺悟ァ狗せ縺ィ縺ェ繧菊dge縺ョ邨らせ縺ィ縺ェ繧逆arget縺瑚�ェ霄ォ縲√b縺励¥縺ッ蟄伜惠縺励↑縺�蝣エ蜷医r髯、縺� if ((cur != target) && (target != null)) { - // edgeの種類が"dashed"の場合 + // edge縺ョ遞ョ鬘槭′"dashed"縺ョ蝣エ蜷� if ("true".equals(state.getStyle().get("dashed"))) { - state.getStyle().put("strokeColor", "#800080"); // edgeの色を変更 - dotEdges.get(cur).add(target); // dotEdges{key : 始点となるcell, value : 終点となるcell} + state.getStyle().put("strokeColor", "#800080"); // edge縺ョ濶イ繧貞、画峩 + dotEdges.get(cur).add(target); // dotEdges{key : 蟋狗せ縺ィ縺ェ繧議ell, value : 邨らせ縺ィ縺ェ繧議ell} } else { tagCount++; - // 始点として複数回参照されている場合 + // 蟋狗せ縺ィ縺励※隍�謨ー蝗槫盾辣ァ縺輔l縺ヲ縺�繧句�エ蜷� if (tagCount > 1) { - // curまでのlineの情報を再構築して、そこから新しいlineを構築する + // cur縺セ縺ァ縺ョline縺ョ諠�蝣ア繧貞�肴ァ狗ッ峨@縺ヲ縲√◎縺薙°繧画眠縺励>line繧呈ァ狗ッ峨☆繧� List newline = new ArrayList(lines.get(lines.size() - 1)); while (newline.get(newline.size() - 1).getId() != cur.getId()) { newline.remove(newline.size() - 1); } lines.add(newline); constructionLine(target, d + 1); - // 始点として初めて参照された場合 + // 蟋狗せ縺ィ縺励※蛻昴a縺ヲ蜿ら�ァ縺輔l縺溷�エ蜷� } else { constructionLine(target, d + 1); } @@ -229,13 +229,13 @@ } } - // cellの距離を再計算する + // cell縺ョ霍晞屬繧貞�崎ィ育ョ励☆繧� public void reculcDist() { - // 距離の更新が行われなくなるまで繰り返す + // 霍晞屬縺ョ譖エ譁ー縺瑚。後o繧後↑縺上↑繧九∪縺ァ郢ー繧願ソ斐☆ while (true) { boolean isChanging = false; - // 同一のlineに含まれる自身の1つ手前の距離と自身の距離を比較して、正しい距離を計算 + // 蜷御ク�縺ョline縺ォ蜷ォ縺セ繧後k閾ェ霄ォ縺ョ1縺、謇句燕縺ョ霍晞屬縺ィ閾ェ霄ォ縺ョ霍晞屬繧呈ッ碑シ�縺励※縲∵ュ」縺励>霍晞屬繧定ィ育ョ� for (List line : lines) { for (int i = 1; i < line.size(); i++) { mxCell cur = line.get(i); @@ -251,7 +251,7 @@ } } - // 階層構造を考慮したcellの距離を計算 + // 髫主ア、讒矩��繧定��諷ョ縺励◆cell縺ョ霍晞屬繧定ィ育ョ� for (mxCell r : roots) { for (mxCell c : hierarchicalRecursionOrder.get(r)) { mxCell p = (mxCell) graphModel.getParent(c); @@ -274,28 +274,28 @@ } } - // 1度も変更が無いとループを抜ける + // 1蠎ヲ繧ょ、画峩縺檎┌縺�縺ィ繝ォ繝シ繝励r謚懊¢繧� if (!isChanging) { break; } } } - // lineをソートする(ただし、実際にはlines内の要素の順番は入れ替えず、呼び出す順番を保存したorderを作成) + // line繧偵た繝シ繝医☆繧�(縺溘□縺励�∝ョ滄圀縺ォ縺ッlines蜀�縺ョ隕∫エ�縺ョ鬆�逡ェ縺ッ蜈・繧梧崛縺医★縲∝他縺ウ蜃コ縺咎��逡ェ繧剃ソ晏ュ倥@縺殪rder繧剃ス懈��) public void sortLines() { for (int i = 0; i < lines.size(); i++) { List line = lines.get(i); - // eventChannelからの出力先がrootである場合 + // eventChannel縺九i縺ョ蜃コ蜉帛�医′root縺ァ縺ゅk蝣エ蜷� if (roots.contains(line.get(1))) { for (mxCell c : line) { - addLine(c); // orderにlineのindexを格納する + addLine(c); // order縺ォline縺ョindex繧呈�シ邏阪☆繧� } } } } - // orderにlineのindexを格納する + // order縺ォline縺ョindex繧呈�シ邏阪☆繧� public void addLine(mxCell c) { if (cellToLineIndex.get(c) != null) { for (int i : cellToLineIndex.get(c)) { @@ -306,32 +306,32 @@ } } - // rootが属するlineのindexを格納した後、子孫が属するlineのindexを順次格納する + // root縺悟ア槭☆繧詰ine縺ョindex繧呈�シ邏阪@縺溷セ後�∝ュ仙ュォ縺悟ア槭☆繧詰ine縺ョindex繧帝��谺。譬シ邏阪☆繧� for (int i = 0; i < graphModel.getChildCount(c); i++) { mxCell child = (mxCell) graphModel.getChildAt(c, i); addLine(child); } } - // cellを配置する + // cell繧帝�咲スョ縺吶k public void layout1(mxCell s) { - /* cellの座標は、cellのparentの左上の座標を基準にxとyをどれだけずらすかで定義されている - よって計算の都合上、id=1 のcell(レイアウト画面)の左上を基準にした座標をcellGeoに保存しておく */ + /* cell縺ョ蠎ァ讓吶�ッ縲…ell縺ョparent縺ョ蟾ヲ荳翫�ョ蠎ァ讓吶r蝓コ貅悶↓x縺ィy繧偵←繧後□縺代★繧峨☆縺九〒螳夂セゥ縺輔l縺ヲ縺�繧� + 繧医▲縺ヲ險育ョ励�ョ驛ス蜷井ク翫�(d=1 縺ョcell(繝ャ繧、繧「繧ヲ繝育判髱「)縺ョ蟾ヲ荳翫r蝓コ貅悶↓縺励◆蠎ァ讓吶rcellGeo縺ォ菫晏ュ倥@縺ヲ縺翫¥ */ - Set movedSet = new HashSet<>(); // 配置済みのcellを管理 - Map> movedMap = new TreeMap<>(); // 配置済みのcellの距離ごとの配置順を管理 - Map distToMaxX = new HashMap<>(); // 距離ごとのcellの右端のx座標の最大値を管理 + Set movedSet = new HashSet<>(); // 驟咲スョ貂医∩縺ョcell繧堤ョ。逅� + Map> movedMap = new TreeMap<>(); // 驟咲スョ貂医∩縺ョcell縺ョ霍晞屬縺斐→縺ョ驟咲スョ鬆�繧堤ョ。逅� + Map distToMaxX = new HashMap<>(); // 霍晞屬縺斐→縺ョcell縺ョ蜿ウ遶ッ縺ョx蠎ァ讓吶�ョ譛�螟ァ蛟、繧堤ョ。逅� double maxY = 0; int maxD = 0; putCellGeo(s, 0, 0); - // 距離の最大値を求める + // 霍晞屬縺ョ譛�螟ァ蛟、繧呈アゅa繧� for (mxCell c : cells) { maxD = Math.max(maxD, vertexToDist.get(c).get(1)); } - // 初期化 + // 蛻晄悄蛹� distToMaxX.put(-1, 0.0); for (int d = 0; d <= maxD; d++) { movedMap.put(d, new ArrayList<>()); @@ -339,28 +339,28 @@ } for (int i : order) { - double centerY = -1; // 配置予定のy座標(中央) + double centerY = -1; // 驟咲スョ莠亥ョ壹�ョy蠎ァ讓�(荳ュ螟ョ) for (mxCell cur : lines.get(i)) { - // 既に配置済みならスキップ + // 譌「縺ォ驟咲スョ貂医∩縺ェ繧峨せ繧ュ繝�繝� if (movedSet.contains(cur)) { continue; } - int d = vertexToDist.get(cur).get(0); // curの距離 - double x = distToMaxX.get(d - 1) + MOVE_X; // 配置予定のx座標 - double endX = 0; // 配置したcellの右端のx座標 - double endY = 0; // 配置したcellの下端のy座標 + int d = vertexToDist.get(cur).get(0); // cur縺ョ霍晞屬 + double x = distToMaxX.get(d - 1) + MOVE_X; // 驟咲スョ莠亥ョ壹�ョx蠎ァ讓� + double endX = 0; // 驟咲スョ縺励◆cell縺ョ蜿ウ遶ッ縺ョx蠎ァ讓� + double endY = 0; // 驟咲スョ縺励◆cell縺ョ荳狗ォッ縺ョy蠎ァ讓� - // curがroot, channel, eventChannelに属するcellである場合 + // cur縺罫oot, channel, eventChannel縺ォ螻槭☆繧議ell縺ァ縺ゅk蝣エ蜷� if (roots.contains(cur) || channels.contains(cur) || eventChannels.contains(cur)) { if (centerY == -1) { centerY = maxY + MOVE_Y + cur.getGeometry().getHeight() / 2; } - double y = centerY - cur.getGeometry().getHeight() / 2; // 配置予定のy座標 + double y = centerY - cur.getGeometry().getHeight() / 2; // 驟咲スョ莠亥ョ壹�ョy蠎ァ讓� double ny = y; double nx = x; - // 予定している座標に配置すると他のリソース内部に配置されてしまう場合、下にずらす + // 莠亥ョ壹@縺ヲ縺�繧句コァ讓吶↓驟咲スョ縺吶k縺ィ莉悶�ョ繝ェ繧ス繝シ繧ケ蜀�驛ィ縺ォ驟咲スョ縺輔l縺ヲ縺励∪縺�蝣エ蜷医�∽ク九↓縺壹i縺� for (mxCell m : movedSet) { if (roots.contains(m) || channels.contains(m)) { if (cellOverlap(m.getGeometry().getX(), m.getGeometry().getY(), m.getGeometry().getWidth(), m.getGeometry().getHeight(), x, y, cur.getGeometry().getWidth(), cur.getGeometry().getHeight())) { @@ -369,7 +369,7 @@ } } - // 予定の座標に配置して、各種処理を行う + // 莠亥ョ壹�ョ蠎ァ讓吶↓驟咲スョ縺励※縲∝推遞ョ蜃ヲ逅�繧定。後≧ cur.getGeometry().setX(nx); cur.getGeometry().setY(ny); endX = nx + cur.getGeometry().getWidth(); @@ -378,26 +378,26 @@ addMoved(movedSet, movedMap, cur, d); graphModel.setGeometry(cur, (mxGeometry) cur.getGeometry().clone()); - // 距離がdの最大のx座標が更新される場合、既に配置済みのcellをそれに応じて右にずらす + // 霍晞屬縺慧縺ョ譛�螟ァ縺ョx蠎ァ讓吶′譖エ譁ー縺輔l繧句�エ蜷医�∵里縺ォ驟咲スョ貂医∩縺ョcell繧偵◎繧後↓蠢懊§縺ヲ蜿ウ縺ォ縺壹i縺� if (distToMaxX.get(d) < endX) { updateDistToMaxX(distToMaxX, movedSet, movedMap, d, maxD, endX); } - maxY = Math.max(maxY, endY); // 配置済みのcellの中での下端の座標の最大 + maxY = Math.max(maxY, endY); // 驟咲スョ貂医∩縺ョcell縺ョ荳ュ縺ァ縺ョ荳狗ォッ縺ョ蠎ァ讓吶�ョ譛�螟ァ - // rootの子孫をまとめて配置する + // root縺ョ蟄仙ュォ繧偵∪縺ィ繧√※驟咲スョ縺吶k for (mxCell c : hierarchicalRecursionOrder.get(cur)) { d = vertexToDist.get(c).get(0); - nx = x; // 配置予定のx座標 + nx = x; // 驟咲スョ莠亥ョ壹�ョx蠎ァ讓� mxCell parent = (mxCell) graphModel.getParent(c); - // 距離が親と等しい場合、親のx座標より少し大きくする + // 霍晞屬縺瑚ヲェ縺ィ遲峨@縺�蝣エ蜷医�∬ヲェ縺ョx蠎ァ讓吶h繧雁ー代@螟ァ縺阪¥縺吶k if (d == vertexToDist.get(parent).get(0)) { nx = cellGeo.get(parent).get("x") + MARGIN_WIDTH; } else { nx = distToMaxX.get(d - 1) + MOVE_X; } - // 重なってしまう兄弟リソースが存在する場合、下にずらす + // 驥阪↑縺」縺ヲ縺励∪縺�蜈�蠑溘Μ繧ス繝シ繧ケ縺悟ュ伜惠縺吶k蝣エ蜷医�∽ク九↓縺壹i縺� double brotherMaxY = MOVE_Y; for (int k = 0; k < graphModel.getChildCount(parent); k++) { mxCell child = (mxCell) graphModel.getChildAt(parent, k); @@ -410,7 +410,7 @@ } } - // 予定の座標に配置して、各種処理を行う + // 莠亥ョ壹�ョ蠎ァ讓吶↓驟咲スョ縺励※縲∝推遞ョ蜃ヲ逅�繧定。後≧ c.getGeometry().setX(nx - cellGeo.get(parent).get("x")); c.getGeometry().setY(brotherMaxY); graphModel.setGeometry(c, (mxGeometry) c.getGeometry().clone()); @@ -419,9 +419,9 @@ endX = cellGeo.get(c).get("x") + c.getGeometry().getWidth(); endY = cellGeo.get(c).get("y") + c.getGeometry().getHeight(); - endY = resize(parent, endX, endY); // 子孫が親の内部に含まれない場合、親の大きさを変更する + endY = resize(parent, endX, endY); // 蟄仙ュォ縺瑚ヲェ縺ョ蜀�驛ィ縺ォ蜷ォ縺セ繧後↑縺�蝣エ蜷医�∬ヲェ縺ョ螟ァ縺阪&繧貞、画峩縺吶k - // 距離がdの最大のx座標が更新される場合、既に配置済みのcellをそれに応じて右にずらす + // 霍晞屬縺慧縺ョ譛�螟ァ縺ョx蠎ァ讓吶′譖エ譁ー縺輔l繧句�エ蜷医�∵里縺ォ驟咲スョ貂医∩縺ョcell繧偵◎繧後↓蠢懊§縺ヲ蜿ウ縺ォ縺壹i縺� if (distToMaxX.get(d) < endX) { updateDistToMaxX(distToMaxX, movedSet, movedMap, d, maxD, endX); } @@ -431,13 +431,13 @@ } } - // 点線の辺が重なっている場合、右にずらす + // 轤ケ邱壹�ョ霎コ縺碁㍾縺ェ縺」縺ヲ縺�繧句�エ蜷医�∝承縺ォ縺壹i縺� for (mxCell c : resources) { for (mxCell cc : dotEdges.get(c)) { for (Map.Entry> entry : dotEdges.entrySet()) { mxCell u = entry.getKey(); for (mxCell v : entry.getValue()) { - // c-cc, u-vが同じdotEdgeを参照している場合 + // c-cc, u-v縺悟酔縺賄otEdge繧貞盾辣ァ縺励※縺�繧句�エ蜷� if ((c == u && cc == v) || (c == v && cc == u)) { continue; } @@ -460,7 +460,7 @@ } } - // eventChannelを出力先のy座標に揃える + // eventChannel繧貞�コ蜉帛�医�ョy蠎ァ讓吶↓謠�縺医k for (int i : order) { mxCell cur = lines.get(i).get(1); List ecs = new ArrayList<>(); @@ -493,7 +493,7 @@ } } - // eventChannelをy座標について昇順にソートする + // eventChannel繧馳蠎ァ讓吶↓縺、縺�縺ヲ譏�鬆�縺ォ繧ス繝シ繝医☆繧� List sortedEcs = new ArrayList<>(); Set usedEcs = new HashSet<>(); for (int i = 0; i < eventChannels.size(); i++) { @@ -512,7 +512,7 @@ usedEcs.add(minEc); } - // ソートの順番に応じて、重なっているeventChannelを下にずらす + // 繧ス繝シ繝医�ョ鬆�逡ェ縺ォ蠢懊§縺ヲ縲�驥阪↑縺」縺ヲ縺�繧菊ventChannel繧剃ク九↓縺壹i縺� for (int i = 1; i < sortedEcs.size(); i++) { mxCell cur = sortedEcs.get(i); mxCell pre = sortedEcs.get(i - 1); @@ -526,25 +526,25 @@ } } - // cellを配置する + // cell繧帝�咲スョ縺吶k public void layout2(mxCell s) { - /* cellの座標は、cellのparentの左上の座標を基準にxとyをどれだけずらすかで定義されている - よって計算の都合上、id=1 のcell(レイアウト画面)の左上を基準にした座標をcellGeoに保存しておく */ + /* cell縺ョ蠎ァ讓吶�ッ縲…ell縺ョparent縺ョ蟾ヲ荳翫�ョ蠎ァ讓吶r蝓コ貅悶↓x縺ィy繧偵←繧後□縺代★繧峨☆縺九〒螳夂セゥ縺輔l縺ヲ縺�繧� + 繧医▲縺ヲ險育ョ励�ョ驛ス蜷井ク翫�(d=1 縺ョcell(繝ャ繧、繧「繧ヲ繝育判髱「)縺ョ蟾ヲ荳翫r蝓コ貅悶↓縺励◆蠎ァ讓吶rcellGeo縺ォ菫晏ュ倥@縺ヲ縺翫¥ */ - Set movedSet = new HashSet<>(); // 配置済みのcellを管理 - Map> movedMap = new TreeMap<>(); // 配置済みのcellの距離ごとの配置順を管理 - Map distToMaxX = new HashMap<>(); // 距離ごとのcellの右端のx座標の最大値を管理 + Set movedSet = new HashSet<>(); // 驟咲スョ貂医∩縺ョcell繧堤ョ。逅� + Map> movedMap = new TreeMap<>(); // 驟咲スョ貂医∩縺ョcell縺ョ霍晞屬縺斐→縺ョ驟咲スョ鬆�繧堤ョ。逅� + Map distToMaxX = new HashMap<>(); // 霍晞屬縺斐→縺ョcell縺ョ蜿ウ遶ッ縺ョx蠎ァ讓吶�ョ譛�螟ァ蛟、繧堤ョ。逅� double maxY = 0; int maxD = 0; putCellGeo(s, 0, 0); - // 距離の最大値を求める + // 霍晞屬縺ョ譛�螟ァ蛟、繧呈アゅa繧� for (mxCell c : cells) { maxD = Math.max(maxD, vertexToDist.get(c).get(1)); } - // 初期化 + // 蛻晄悄蛹� distToMaxX.put(-1, 0.0); for (int d = 0; d <= maxD; d++) { movedMap.put(d, new ArrayList<>()); @@ -552,30 +552,30 @@ } for (int i : order) { - double centerY = -1; // 配置予定のy座標(中央) + double centerY = -1; // 驟咲スョ莠亥ョ壹�ョy蠎ァ讓�(荳ュ螟ョ) for (int j = 0; j < lines.get(i).size(); j++) { mxCell cur = lines.get(i).get(j); - // 既に配置済みならスキップ + // 譌「縺ォ驟咲スョ貂医∩縺ェ繧峨せ繧ュ繝�繝� if (movedSet.contains(cur)) { continue; } - int d = vertexToDist.get(cur).get(0); // curの距離 - double x = distToMaxX.get(d - 1) + MOVE_X; // 配置予定のx座標 - double endX = 0; // 配置したcellの右端のx座標 - double endY = 0; // 配置したcellの下端のy座標 + int d = vertexToDist.get(cur).get(0); // cur縺ョ霍晞屬 + double x = distToMaxX.get(d - 1) + MOVE_X; // 驟咲スョ莠亥ョ壹�ョx蠎ァ讓� + double endX = 0; // 驟咲スョ縺励◆cell縺ョ蜿ウ遶ッ縺ョx蠎ァ讓� + double endY = 0; // 驟咲スョ縺励◆cell縺ョ荳狗ォッ縺ョy蠎ァ讓� - // curがrootsとeventChannelに属するときのcellの配置 + // cur縺罫oots縺ィeventChannel縺ォ螻槭☆繧九→縺阪�ョcell縺ョ驟咲スョ if (roots.contains(cur) || eventChannels.contains(cur)) { if (centerY == -1) { centerY = maxY + MOVE_Y + cur.getGeometry().getHeight() / 2; } - double y = centerY - cur.getGeometry().getHeight() / 2; // 配置予定のy座標 + double y = centerY - cur.getGeometry().getHeight() / 2; // 驟咲スョ莠亥ョ壹�ョy蠎ァ讓� double ny = y; double nx = x; - // 予定の座標に配置して、各種処理を行う + // 莠亥ョ壹�ョ蠎ァ讓吶↓驟咲スョ縺励※縲∝推遞ョ蜃ヲ逅�繧定。後≧ cur.getGeometry().setX(nx); cur.getGeometry().setY(ny); endX = nx + cur.getGeometry().getWidth(); @@ -584,26 +584,26 @@ addMoved(movedSet, movedMap, cur, d); graphModel.setGeometry(cur, (mxGeometry) cur.getGeometry().clone()); - // 距離がdの最大のx座標が更新される場合、既に配置済みのcellをそれに応じて右にずらす + // 霍晞屬縺慧縺ョ譛�螟ァ縺ョx蠎ァ讓吶′譖エ譁ー縺輔l繧句�エ蜷医�∵里縺ォ驟咲スョ貂医∩縺ョcell繧偵◎繧後↓蠢懊§縺ヲ蜿ウ縺ォ縺壹i縺� if (distToMaxX.get(d) < endX) { updateDistToMaxX(distToMaxX, movedSet, movedMap, d, maxD, endX); } - maxY = Math.max(maxY, endY); // 配置済みのcellの中での下端の座標の最大 + maxY = Math.max(maxY, endY); // 驟咲スョ貂医∩縺ョcell縺ョ荳ュ縺ァ縺ョ荳狗ォッ縺ョ蠎ァ讓吶�ョ譛�螟ァ - // rootの子孫をまとめて配置する + // root縺ョ蟄仙ュォ繧偵∪縺ィ繧√※驟咲スョ縺吶k for (mxCell c : hierarchicalRecursionOrder.get(cur)) { d = vertexToDist.get(c).get(0); - nx = x; // 配置予定のx座標 + nx = x; // 驟咲スョ莠亥ョ壹�ョx蠎ァ讓� mxCell parent = (mxCell) graphModel.getParent(c); - // 距離が親と等しい場合、親のx座標より少し大きくする + // 霍晞屬縺瑚ヲェ縺ィ遲峨@縺�蝣エ蜷医�∬ヲェ縺ョx蠎ァ讓吶h繧雁ー代@螟ァ縺阪¥縺吶k if (d == vertexToDist.get(parent).get(0)) { nx = cellGeo.get(parent).get("x") + MARGIN_WIDTH; } else { nx = distToMaxX.get(d - 1) + MOVE_X; } - // 重なってしまう兄弟リソースが存在する場合、下にずらす + // 驥阪↑縺」縺ヲ縺励∪縺�蜈�蠑溘Μ繧ス繝シ繧ケ縺悟ュ伜惠縺吶k蝣エ蜷医�∽ク九↓縺壹i縺� double brotherMaxY = MOVE_Y; for (int k = 0; k < graphModel.getChildCount(parent); k++) { mxCell child = (mxCell) graphModel.getChildAt(parent, k); @@ -616,7 +616,7 @@ } } - // 予定の座標に配置して、各種処理を行う + // 莠亥ョ壹�ョ蠎ァ讓吶↓驟咲スョ縺励※縲∝推遞ョ蜃ヲ逅�繧定。後≧ c.getGeometry().setX(nx - cellGeo.get(parent).get("x")); c.getGeometry().setY(brotherMaxY); graphModel.setGeometry(c, (mxGeometry) c.getGeometry().clone()); @@ -625,17 +625,17 @@ endX = cellGeo.get(c).get("x") + c.getGeometry().getWidth(); endY = cellGeo.get(c).get("y") + c.getGeometry().getHeight(); - endY = resize(parent, endX, endY); // 子孫が親の内部に含まれない場合、親の大きさを変更する + endY = resize(parent, endX, endY); // 蟄仙ュォ縺瑚ヲェ縺ョ蜀�驛ィ縺ォ蜷ォ縺セ繧後↑縺�蝣エ蜷医�∬ヲェ縺ョ螟ァ縺阪&繧貞、画峩縺吶k - // 距離がdの最大のx座標が更新される場合、既に配置済みのcellをそれに応じて右にずらす + // 霍晞屬縺慧縺ョ譛�螟ァ縺ョx蠎ァ讓吶′譖エ譁ー縺輔l繧句�エ蜷医�∵里縺ォ驟咲スョ貂医∩縺ョcell繧偵◎繧後↓蠢懊§縺ヲ蜿ウ縺ォ縺壹i縺� if (distToMaxX.get(d) < endX) { updateDistToMaxX(distToMaxX, movedSet, movedMap, d, maxD, endX); } - maxY = Math.max(maxY, endY); // 配置済みのcellの中での下端の座標の最大 + maxY = Math.max(maxY, endY); // 驟咲スョ貂医∩縺ョcell縺ョ荳ュ縺ァ縺ョ荳狗ォッ縺ョ蠎ァ讓吶�ョ譛�螟ァ } } - // curがchannelに属するときのcellの配置 + // cur縺慶hannel縺ォ螻槭☆繧九→縺阪�ョcell縺ョ驟咲スョ if (channels.contains(cur)) { mxCell pre = lines.get(i).get(j - 1); centerY = cellGeo.get(pre).get("y") + pre.getGeometry().getHeight() / 2; @@ -649,16 +649,16 @@ addMoved(movedSet, movedMap, cur, d); graphModel.setGeometry(cur, (mxGeometry) cur.getGeometry().clone()); - // 距離がdの最大のx座標が更新される場合、既に配置済みのcellをそれに応じて右にずらす + // 霍晞屬縺慧縺ョ譛�螟ァ縺ョx蠎ァ讓吶′譖エ譁ー縺輔l繧句�エ蜷医�∵里縺ォ驟咲スョ貂医∩縺ョcell繧偵◎繧後↓蠢懊§縺ヲ蜿ウ縺ォ縺壹i縺� if (distToMaxX.get(d) < endX) { updateDistToMaxX(distToMaxX, movedSet, movedMap, d, maxD, endX); } - maxY = Math.max(maxY, endY); // 配置済みのcellの中での下端の座標の最大 + maxY = Math.max(maxY, endY); // 驟咲スョ貂医∩縺ョcell縺ョ荳ュ縺ァ縺ョ荳狗ォッ縺ョ蠎ァ讓吶�ョ譛�螟ァ } } } - // 点線の辺が重なっている場合、右にずらす + // 轤ケ邱壹�ョ霎コ縺碁㍾縺ェ縺」縺ヲ縺�繧句�エ蜷医�∝承縺ォ縺壹i縺� for (mxCell c : resources) { for (mxCell cc : dotEdges.get(c)) { for (Map.Entry> entry : dotEdges.entrySet()) { @@ -686,7 +686,7 @@ } } - // eventChannelを出力先のy座標に揃える + // eventChannel繧貞�コ蜉帛�医�ョy蠎ァ讓吶↓謠�縺医k for (int i : order) { mxCell cur = lines.get(i).get(1); List ecs = new ArrayList<>(); @@ -719,7 +719,7 @@ } } - // eventChannelをy座標について昇順にソートする + // eventChannel繧馳蠎ァ讓吶↓縺、縺�縺ヲ譏�鬆�縺ォ繧ス繝シ繝医☆繧� List sortedEcs = new ArrayList<>(); Set usedEcs = new HashSet<>(); for (int i = 0; i < eventChannels.size(); i++) { @@ -738,7 +738,7 @@ usedEcs.add(minEc); } - // ソートの順番に応じて、重なっているeventChannelを下にずらす + // 繧ス繝シ繝医�ョ鬆�逡ェ縺ォ蠢懊§縺ヲ縲�驥阪↑縺」縺ヲ縺�繧菊ventChannel繧剃ク九↓縺壹i縺� for (int i = 1; i < sortedEcs.size(); i++) { mxCell cur = sortedEcs.get(i); mxCell pre = sortedEcs.get(i - 1); @@ -752,20 +752,20 @@ } } - // cellの座標を登録 + // cell縺ョ蠎ァ讓吶r逋サ骭イ public void putCellGeo(mxCell c, double x, double y) { cellGeo.put(c, new HashMap<>()); cellGeo.get(c).put("x", x); cellGeo.get(c).put("y", y); } - // movedSet, movedMapに配置済みのcellを追加 + // movedSet, movedMap縺ォ驟咲スョ貂医∩縺ョcell繧定ソス蜉� public void addMoved(Set ms, Map> mm, mxCell c, int d) { ms.add(c); mm.get(d).add(c); } - // 2つの辺が重なっているか判定 + // 2縺、縺ョ霎コ縺碁㍾縺ェ縺」縺ヲ縺�繧九°蛻、螳� public boolean isStraightLine(double []u1, double []v1, double []u2, double []v2) { double gradient1 = 0; double length1 = Math.pow(u1[0] - v1[0], 2) + Math.pow(u1[1] - v1[1], 2); @@ -826,7 +826,7 @@ } } - // 2つのcellが重なっているか判定 + // 2縺、縺ョcell縺碁㍾縺ェ縺」縺ヲ縺�繧九°蛻、螳� public boolean cellOverlap(double ax, double ay, double aw, double ah, double bx, double by, double bw, double bh) { if (((ax <= bx) && (bx <= ax + aw)) || ((bx <= ax) && (ax <= bx + bw))) { if (((ay <= by) && (by <= ay + ah)) || ((by <= ay) && (ay <= by + bh))) { @@ -836,7 +836,7 @@ return false; } - // 深さがdのdistToMaxXに更新が入ると、深さがdより大きい配置済みのcellを右にずらす + // 豺ア縺輔′d縺ョdistToMaxX縺ォ譖エ譁ー縺悟�・繧九→縲∵キア縺輔′d繧医j螟ァ縺阪>驟咲スョ貂医∩縺ョcell繧貞承縺ォ縺壹i縺� public void updateDistToMaxX(Map distToMaxX, Set movedSet, Map> movedMap, int d, int md, double endX) { double preEndX = distToMaxX.get(d); distToMaxX.replace(d, endX); @@ -872,7 +872,7 @@ } } - // 子を覆うように親の大きさを変更 + // 蟄舌r隕�縺�繧医≧縺ォ隕ェ縺ョ螟ァ縺阪&繧貞、画峩 public double resize(mxCell ancestor, double endX, double endY) { while (true) { boolean isChanging = false; @@ -901,7 +901,7 @@ return endY; } - // x座標を変更 + // x蠎ァ讓吶r螟画峩 public void relocateX(mxCell c, double nx, double dx) { c.getGeometry().setX(nx - dx); graphModel.setGeometry(c, (mxGeometry) c.getGeometry().clone()); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index acfbf44..5db9ecd 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -436,10 +436,10 @@ for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { refs.add(res); - String refResName = langSpec.toComponentName(res.getResourceName()); - component.addField(langSpec.newFieldDeclaration(new Type(refResName, refResName), res.getResourceName())); - constructor.addParameter(langSpec.newVariableDeclaration(new Type(refResName, refResName), res.getResourceName())); - constructor.getBody().addStatement(langSpec.getFieldAccessor(res.getResourceName()) + langSpec.getAssignment() + res.getResourceName() + langSpec.getStatementDelimiter()); + String refResName = langSpec.toComponentName(res.getLeafResourceName()); + component.addField(langSpec.newFieldDeclaration(new Type(refResName, refResName), res.getLeafResourceName())); + constructor.addParameter(langSpec.newVariableDeclaration(new Type(refResName, refResName), res.getLeafResourceName())); + constructor.getBody().addStatement(langSpec.getFieldAccessor(res.getLeafResourceName()) + langSpec.getAssignment() + res.getLeafResourceName() + langSpec.getStatementDelimiter()); } } } @@ -499,7 +499,7 @@ : DataConstraintModel.typeInt); } // use the cached value as the current state - return new Field(targetRes.getResourceName(), + return new Field(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -507,7 +507,7 @@ @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { ResourcePath targerRes= target.getResource(); - return new Parameter(targerRes.getResourceName(), + return new Parameter(targerRes.getLeafResourceName(), targerRes.getResourceStateType() != null ? targerRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -520,7 +520,7 @@ : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -589,7 +589,7 @@ } // for reference channel member Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(targetRes.getResourceName(), targetRes.getResourceStateType())); + getter.addChild(new Field(targetRes.getLeafResourceName(), targetRes.getResourceStateType())); return getter; } else { // access from the outside of the hierarchy @@ -653,7 +653,7 @@ : DataConstraintModel.typeInt); } // use the cached value as the current state - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -661,7 +661,7 @@ @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { ResourcePath targerRes= target.getResource(); - return new Parameter(targerRes.getResourceName(), + return new Parameter(targerRes.getLeafResourceName(), targerRes.getResourceStateType() != null ? targerRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -674,7 +674,7 @@ : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index d562e39..d086ffb 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -698,11 +698,11 @@ String[] sideEffects = new String[] {""}; if (!isContainedPush) { // All incoming edges are in PULL-style. - String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor()).toImplementation(sideEffects); + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor()).getKey().toImplementation(sideEffects); stateGetter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); } else { // At least one incoming edge is in PUSH-style. - String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor(), inputResourceToStateAccessor).toImplementation(sideEffects); + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor(), inputResourceToStateAccessor).getKey().toImplementation(sideEffects); stateGetter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); } break; @@ -805,11 +805,11 @@ parameters.add(chParam); // A channel parameter to specify the context of the collaboration. } } - parameters.add(langSpec.newVariableDeclaration(srcResPath.getResourceStateType(), srcResPath.getResourceName())); // The state of the source resource to carry the data-flow. + parameters.add(langSpec.newVariableDeclaration(srcResPath.getResourceStateType(), srcResPath.getLeafResourceName())); // The state of the source resource to carry the data-flow. // For the refs. for (ResourcePath ref: ch.getReferenceResources()) { if (!resourceNode.getInSideResources().contains(ref)) { - parameters.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + parameters.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getLeafResourceName())); } } MethodDeclaration update = null; @@ -844,7 +844,7 @@ if (resourceNode.getInSideResources().contains(out.getResource())) { Expression updateExp = null; if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor()); + updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor()).getKey(); } else { // if there exists one or more reference channel member. HashMap inputResourceToStateAccessor = new HashMap<>(); @@ -854,7 +854,7 @@ for (ChannelMember c: ch.getReferenceChannelMembers()) { inputResourceToStateAccessor.put(c, getRefAccessor()); } - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(), inputResourceToStateAccessor); + updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(), inputResourceToStateAccessor).getKey(); } // Replace Json constructor with a constructor of the child resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); @@ -964,7 +964,7 @@ // Declare the cache field. FieldDeclaration cacheField = langSpec.newFieldDeclaration( srcResPath.getResourceStateType(), - srcResPath.getResourceName(), + srcResPath.getLeafResourceName(), langSpec.getFieldInitializer(srcResPath.getResourceStateType(), srcResPath.getResourceHierarchy().getInitialValue())); if (component != null) { component.addField(cacheField); @@ -1103,7 +1103,7 @@ referredResources.put(update, referredSet); } if (!resourceNode.getInSideResources().contains(ref)) { - String refVarName = ref.getResourceName(); + String refVarName = ref.getLeafResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(rc, in); @@ -1259,7 +1259,7 @@ Expression varExp = refCm.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); if (varExp != null && varExp instanceof Variable) { if (refCm.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = refCm.getResource().getResourceName(); + refVarName = refCm.getResource().getLeafResourceName(); break; } } @@ -1419,7 +1419,7 @@ // For each reference channel member, get the current state of the reference side resource by pull data transfer. ResourcePath ref = rc.getResource(); if (!out.getResource().equals(ref)) { - String refVarName = ref.getResourceName(); + String refVarName = ref.getLeafResourceName(); Expression refGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, null); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); @@ -1453,7 +1453,7 @@ for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { Expression varExp = rc.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); if (varExp != null && rc.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = rc.getResource().getResourceName(); + refVarName = rc.getResource().getLeafResourceName(); break; } } @@ -1472,7 +1472,7 @@ if (input != null) { // Add a statement to update the state field to the input method. try { - Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getRefAccessor()); + Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getRefAccessor()).getKey(); // Replace Json constructor with a constructor of the child resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { @@ -1601,7 +1601,7 @@ referredResources.put(input, referredSet); } if (!resourceNode.getOutSideResources().contains(ref)) { - String refVarName = ref.getResourceName(); + String refVarName = ref.getLeafResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(rc, in); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index f0b2bc0..1a57882 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -218,7 +218,7 @@ for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { refs.add(res); - String refResName = res.getResourceName(); + String refResName = res.getLeafResourceName(); fieldInitializer += toVariableName(refResName) + ","; f = true; } @@ -550,10 +550,10 @@ params.add(chParam); // A channel parameter to specify the context of the collaboration. } } - params.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); // The state of the source resource to carry the data-flow. + params.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getLeafResourceName())); // The state of the source resource to carry the data-flow. for (ResourcePath ref: ch.getReferenceResources()) { if (!ref.equals(resourceNode.getInSideResource(ch))) { - params.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + params.add(new VariableDeclaration(ref.getResourceStateType(), ref.getLeafResourceName())); } } MethodDeclaration update = null; @@ -609,8 +609,8 @@ if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { refs.add(res); String refResName = getComponentName(res.getResourceHierarchy()); - FieldDeclaration refResField = new FieldDeclaration(new Type(refResName, refResName), res.getResourceName()); - VariableDeclaration refResVar = new VariableDeclaration(new Type(refResName, refResName), res.getResourceName()); + FieldDeclaration refResField = new FieldDeclaration(new Type(refResName, refResName), res.getLeafResourceName()); + VariableDeclaration refResVar = new VariableDeclaration(new Type(refResName, refResName), res.getLeafResourceName()); if (component != null) { // A component is created for this resource. component.addField(refResField); @@ -671,7 +671,7 @@ Expression varExp = refCm.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); if (varExp != null && varExp instanceof Variable) { if (refCm.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = refCm.getResource().getResourceName(); + refVarName = refCm.getResource().getLeafResourceName(); break; } } @@ -1145,7 +1145,7 @@ : DataConstraintModel.typeInt); } // use the cached value as the current state - return new Field(targetRes.getResourceName(), + return new Field(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1153,7 +1153,7 @@ @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { ResourcePath targetRes = target.getResource(); - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1166,7 +1166,7 @@ : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1233,7 +1233,7 @@ } // for reference channel member Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(targetRes.getResourceName(), targetRes.getResourceStateType())); + getter.addChild(new Field(targetRes.getLeafResourceName(), targetRes.getResourceStateType())); return getter; } else { // access from the outside of the hierarchy @@ -1294,7 +1294,7 @@ : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1302,7 +1302,7 @@ @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { ResourcePath targetRes = target.getResource(); - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1315,7 +1315,7 @@ : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index aef4145..9dfadd7 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -98,7 +98,7 @@ // update stored state of dst side resource (when every incoming edge is in push style) Expression updateExp = null; if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor).getKey(); } else { // if there exists one or more reference channel member. HashMap inputResourceToStateAccessor = new HashMap<>(); @@ -108,7 +108,7 @@ for (ChannelMember c: ch.getReferenceChannelMembers()) { inputResourceToStateAccessor.put(c, JavaCodeGenerator.refAccessor); } - updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor, inputResourceToStateAccessor); + updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor, inputResourceToStateAccessor).getKey(); } // Replace Json constructor with a constructor of the child resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); @@ -301,7 +301,7 @@ referredResources.put(srcUpdate, referredSet); } if (!dst.getInSideResources().contains(ref)) { - String refVarName = ref.getResourceName(); + String refVarName = ref.getLeafResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rc, in); @@ -364,7 +364,7 @@ referredResources.put(srcInput, referredSet); } if (!dst.getInSideResources().contains(ref)) { - String refVarName = ref.getResourceName(); + String refVarName = ref.getLeafResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(rc, in); @@ -441,11 +441,11 @@ // An input resource is outside. if (!isContainedPush) { // All incoming edges are in PULL style. - String curState = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); + String curState = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).getKey().toImplementation(sideEffects); getter.addStatement(sideEffects[0] + "return " + curState + ";"); } else { // At least one incoming edge is in PUSH style. - String curState = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor).toImplementation(sideEffects); + String curState = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor).getKey().toImplementation(sideEffects); getter.addStatement(sideEffects[0] + "return " + curState + ";"); } } @@ -679,7 +679,7 @@ } if (input != null) { // In each resource - Expression updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.refAccessor); + Expression updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.refAccessor).getKey(); // Replace Json constructor with a constructor of the child resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { @@ -754,7 +754,7 @@ referredResources.put(input, referredSet); } if (!out.getResource().equals(ref)) { - String refVarName = ref.getResourceName(); + String refVarName = ref.getLeafResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); Expression refGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, null); @@ -791,7 +791,7 @@ for (ChannelMember rc: ch.getReferenceChannelMembers()) { Expression varExp = rc.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); if (varExp != null && rc.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = rc.getResource().getResourceName(); + refVarName = rc.getResource().getLeafResourceName(); break; } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 14c631a..512ac90 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -587,8 +587,8 @@ params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { if (!refRes.equals(resourceNode.getInSideResource(ch))) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); - if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); + param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getLeafResourceName()); + if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getLeafResourceName() + "\"")); params.add(param); } } @@ -680,8 +680,8 @@ params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { if (!refRes.equals(resourceNode.getInSideResource(ch))) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); - param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); + param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getLeafResourceName()); + param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getLeafResourceName() + "\"")); params.add(param); } } @@ -750,7 +750,7 @@ Expression varExp = refCm.getStateTransition().getMessageExpression().getSubTerm(varEnt.getKey()); if (varExp != null && varExp instanceof Variable) { if (refCm.getStateTransition().getCurStateExpression().contains(varExp)) { - refVarName = refCm.getResource().getResourceName(); + refVarName = refCm.getResource().getLeafResourceName(); break; } } @@ -1204,7 +1204,7 @@ : DataConstraintModel.typeInt); } // use the cached value as the current state - return new Field(targetRes.getResourceName(), + return new Field(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1212,7 +1212,7 @@ @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { ResourcePath targetRes = target.getResource(); - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1238,7 +1238,7 @@ } } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1252,7 +1252,7 @@ return getDirectStateAccessorFor(targetRes, fromRes); } } - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1266,7 +1266,7 @@ : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } else { @@ -1329,7 +1329,7 @@ : DataConstraintModel.typeInt); } // for reference channel member - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } @@ -1337,7 +1337,7 @@ @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { ResourcePath targetRes = target.getResource(); - return new Parameter(targetRes.getResourceName(), + return new Parameter(targetRes.getLeafResourceName(), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 7bde0c7..e20b7ff 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -107,7 +107,7 @@ // update stored state of dst side resource (when every incoming edge is in push style) Expression updateExp = null; if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor).getKey(); } else { // if there exists one or more reference channel member. HashMap inputResourceToStateAccessor = new HashMap<>(); @@ -128,7 +128,7 @@ for (ChannelMember c: ch.getReferenceChannelMembers()) { inputResourceToStateAccessor.put(c, JerseyCodeGenerator.refAccessor); } - updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor); + updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor).getKey(); } // Replace Json constructor with a constructor of the child resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); @@ -418,7 +418,7 @@ referredResources.put(srcUpdate, referredSet); } if (!dst.getInSideResources().contains(ref)) { - String refResourceName = ref.getResourceName(); + String refResourceName = ref.getLeafResourceName(); Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); @@ -534,7 +534,7 @@ referredResources.put(srcInput, referredSet); } if (!dst.getInSideResources().contains(ref)) { - String refResourceName = ref.getResourceName(); + String refResourceName = ref.getLeafResourceName(); Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); @@ -553,7 +553,7 @@ Expression refGetter = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(ref, srcRes); String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - srcInput.addFirstStatement(sideEffects[0] + refTypeName + " " + ref.getResourceName() + " = " + refExp + ";"); + srcInput.addFirstStatement(sideEffects[0] + refTypeName + " " + ref.getLeafResourceName() + " = " + refExp + ";"); } } // Value of a reference side resource. @@ -635,7 +635,7 @@ } if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { // generate a return statement. - Expression curExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor); // no pull data transfer is included. + Expression curExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).getKey(); // no pull data transfer is included. Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pullAccessor); String[] sideEffects = new String[] {""}; String curState = curExp.toImplementation(sideEffects); @@ -643,7 +643,7 @@ // For each reference channel member, get the current state of the reference side resource by pull data transfer. for (ChannelMember rc: ch.getReferenceChannelMembers()) { ResourcePath refRes = rc.getResource(); - String refResourceName = refRes.getResourceName(); + String refResourceName = refRes.getLeafResourceName(); Type refResourceType = refRes.getResourceStateType(); if (rc.isOutside()) { List pathParams = new ArrayList<>(); @@ -672,7 +672,7 @@ for (Expression pathExp: src2.getPathParams()) { pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } - generatePullDataTransfer(getter, src2.getResourceName(), src2.getResourceHierarchy().toResourcePath(pathParams), srcResourceType); + generatePullDataTransfer(getter, src2.getLeafResourceName(), src2.getResourceHierarchy().toResourcePath(pathParams), srcResourceType); } } } @@ -811,7 +811,7 @@ referredResources.put(input, referredSet); } if (!out.getResource().equals(ref)) { - String refResourceName = ref.getResourceName(); + String refResourceName = ref.getLeafResourceName(); Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); @@ -835,7 +835,7 @@ } } } - Expression updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.refAccessor); + Expression updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.refAccessor).getKey(); // Replace Json constructor with a constructor of the child resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java index dcdba9f..047f906 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Symbol.java @@ -1,5 +1,7 @@ package models.algebra; +import java.util.List; + public class Symbol { protected String name; protected String implName; @@ -10,6 +12,7 @@ protected models.algebra.Type[] signature = null; protected int[] implParamOrder = null; protected IImplGenerator generator = null; + protected ICalculator calculator = null; public Symbol(String name) { this.name = name; @@ -66,6 +69,37 @@ } } + public Symbol(String name, int arity, ICalculator calculator) { + this.name = name; + this.arity = arity; + this.calculator = calculator; + } + + public Symbol(String name, int arity, Type operatorType, ICalculator calculator) { + this.name = name; + this.arity = arity; + this.operatorType = operatorType; + this.calculator = calculator; + } + + public Symbol(String name, int arity, Type operatorType, IImplGenerator generator, ICalculator calculator) { + this.name = name; + this.arity = arity; + this.operatorType = operatorType; + this.generator = generator; + this.implOperatorType = Type.GENERATIVE; + this.calculator = calculator; + } + + public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType, ICalculator calculator) { + this.name = name; + this.implName = implName; + this.arity = arity; + this.operatorType = operatorType; + this.implOperatorType = implOperatorType; + this.calculator = calculator; + } + public void setArity(int arity) { this.arity = arity; } @@ -171,6 +205,17 @@ } return null; } + + public boolean isCalculatable() { + return (calculator != null); + } + + public Constant calculate(List args) { + if (calculator != null) { + return calculator.calculate(args); + } + return null; + } public boolean equals(Object another) { if (!(another instanceof Symbol)) return false; @@ -232,4 +277,8 @@ */ public String generate(models.algebra.Type type, models.algebra.Type[] childrenTypes, String children[], String[] childrenSideEffects, String[] sideEffect); } + + public interface ICalculator { + public Constant calculate(List args); + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java index 52d000e..b326caa 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java @@ -149,6 +149,18 @@ } else { return new Term(newSymbol, newChildren); } + } else if (symbol.isCalculatable()) { + List newChildren = new ArrayList<>(); + for (Expression child: children) { + if (child instanceof Term) { + child = ((Term) child).reduce(); + } + if (!(child instanceof Constant)) { + return this; + } + newChildren.add((Constant) child); + } + return symbol.calculate(newChildren); } else { // Calculate inverse map List newChildren = new ArrayList<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java index 93a3cea..9cf0280 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ChannelMember.java @@ -41,13 +41,13 @@ @Override public String toString() { if (stateTransition.getNextStateExpression() == null) { - return resourcePath.getResourceName() + "(" + return resourcePath.getLeafResourceName() + "(" + stateTransition.getCurStateExpression() + "," + stateTransition.getMessageExpression() + ")"; } - return resourcePath.getResourceName() + "(" + return resourcePath.getLeafResourceName() + "(" + stateTransition.getCurStateExpression() + "," + stateTransition.getMessageExpression() + ")" - + " == " + stateTransition.getNextStateExpression(); + + " = " + stateTransition.getNextStateExpression(); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index f72c44a..7d21e0c 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; +import models.algebra.Constant; import models.algebra.Expression; import models.algebra.LambdaAbstraction; import models.algebra.Symbol; @@ -36,11 +37,282 @@ public static final Type typePairDouble = new Type("Pair", "Pair", "Pair", typePair); public static final Type typeMap = new Type("Map", "HashMap<>", "Map"); public static final JsonType typeJson = new JsonType("Json", "HashMap<>", "Map"); - public static final Symbol add = new Symbol(Parser.ADD, 2, Symbol.Type.INFIX); - public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX); - public static final Symbol sub = new Symbol(Parser.SUB, 2, Symbol.Type.INFIX); - public static final Symbol div = new Symbol(Parser.DIV, 2, Symbol.Type.INFIX); - public static final Symbol minus = new Symbol(Parser.MINUS, 1); + public static final Symbol add = new Symbol(Parser.ADD, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(arg0) + Double.parseDouble(arg1)), typeDouble); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(arg0) + Float.parseFloat(arg1)), typeFloat); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + return new Constant(Long.toString(Long.parseLong(arg0) + Long.parseLong(arg1)), typeLong); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(arg0) + Integer.parseInt(arg1)), typeInt); + } + return new Constant(Integer.toString(Integer.parseInt(arg0) + Integer.parseInt(arg1))); + } + }); + public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(arg0) * Double.parseDouble(arg1)), typeDouble); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(arg0) * Float.parseFloat(arg1)), typeFloat); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + return new Constant(Long.toString(Long.parseLong(arg0) * Long.parseLong(arg1)), typeLong); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(arg0) * Integer.parseInt(arg1)), typeInt); + } + return new Constant(Integer.toString(Integer.parseInt(arg0) * Integer.parseInt(arg1))); + } + }); + public static final Symbol sub = new Symbol(Parser.SUB, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(arg0) - Double.parseDouble(arg1)), typeDouble); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(arg0) - Float.parseFloat(arg1)), typeFloat); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + return new Constant(Long.toString(Long.parseLong(arg0) - Long.parseLong(arg1)), typeLong); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(arg0) - Integer.parseInt(arg1)), typeInt); + } + return new Constant(Integer.toString(Integer.parseInt(arg0) - Integer.parseInt(arg1))); + } + }); + public static final Symbol div = new Symbol(Parser.DIV, 2, Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + return new Constant(Double.toString(Double.parseDouble(arg0) / Double.parseDouble(arg1)), typeDouble); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + return new Constant(Float.toString(Float.parseFloat(arg0) / Float.parseFloat(arg1)), typeFloat); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + return new Constant(Long.toString(Long.parseLong(arg0) / Long.parseLong(arg1)), typeLong); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(arg0) / Integer.parseInt(arg1)), typeInt); + } + return new Constant(Integer.toString(Integer.parseInt(arg0) / Integer.parseInt(arg1))); + } + }); + public static final Symbol mod = new Symbol(Parser.MOD, 2, Symbol.Type.INFIX, "%", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + return new Constant(Long.toString(Long.parseLong(arg0) % Long.parseLong(arg1)), typeLong); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + return new Constant(Integer.toString(Integer.parseInt(arg0) % Integer.parseInt(arg1)), typeInt); + } + return new Constant(Integer.toString(Integer.parseInt(arg0) % Integer.parseInt(arg1))); + } + }); + public static final Symbol minus = new Symbol(Parser.MINUS, 1, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg = args.get(0).getSymbol().toString(); + if (args.get(0).getType().equals(typeDouble)) { + return new Constant(Double.toString(-Double.parseDouble(arg)), typeDouble); + } else if (args.get(0).getType().equals(typeFloat)) { + return new Constant(Float.toString(-Float.parseFloat(arg)), typeFloat); + } else if (args.get(0).getType().equals(typeLong)) { + return new Constant(Long.toString(-Long.parseLong(arg)), typeLong); + } else if (args.get(0).getType().equals(typeInt)) { + return new Constant(Integer.toString(-Integer.parseInt(arg)), typeInt); + } + return new Constant(Integer.toString(-Integer.parseInt(arg))); + } + }); + public static final Symbol eq = new Symbol(Parser.EQ, 2, Symbol.Type.INFIX, "==", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + result = (Double.parseDouble(arg0) == Double.parseDouble(arg1)); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + result = (Float.parseFloat(arg0) == Float.parseFloat(arg1)); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + result = (Long.parseLong(arg0) == Long.parseLong(arg1)); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + result = (Integer.parseInt(arg0) == Integer.parseInt(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol neq = new Symbol(Parser.NEQ, 2, Symbol.Type.INFIX, "!=", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + result = (Double.parseDouble(arg0) != Double.parseDouble(arg1)); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + result = (Float.parseFloat(arg0) != Float.parseFloat(arg1)); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + result = (Long.parseLong(arg0) != Long.parseLong(arg1)); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + result = (Integer.parseInt(arg0) != Integer.parseInt(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol gt = new Symbol(Parser.GT, 2, Symbol.Type.INFIX, ">", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + result = (Double.parseDouble(arg0) > Double.parseDouble(arg1)); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + result = (Float.parseFloat(arg0) > Float.parseFloat(arg1)); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + result = (Long.parseLong(arg0) > Long.parseLong(arg1)); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + result = (Integer.parseInt(arg0) > Integer.parseInt(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol lt = new Symbol(Parser.LT, 2, Symbol.Type.INFIX, "<", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + result = (Double.parseDouble(arg0) < Double.parseDouble(arg1)); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + result = (Float.parseFloat(arg0) < Float.parseFloat(arg1)); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + result = (Long.parseLong(arg0) < Long.parseLong(arg1)); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + result = (Integer.parseInt(arg0) < Integer.parseInt(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol ge = new Symbol(Parser.GE, 2, Symbol.Type.INFIX, ">=", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + result = (Double.parseDouble(arg0) >= Double.parseDouble(arg1)); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + result = (Float.parseFloat(arg0) >= Float.parseFloat(arg1)); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + result = (Long.parseLong(arg0) >= Long.parseLong(arg1)); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + result = (Integer.parseInt(arg0) >= Integer.parseInt(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol le = new Symbol(Parser.LE, 2, Symbol.Type.INFIX, "<=", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeDouble) || args.get(1).getType().equals(typeDouble)) { + result = (Double.parseDouble(arg0) <= Double.parseDouble(arg1)); + } else if (args.get(0).getType().equals(typeFloat) || args.get(1).getType().equals(typeFloat)) { + result = (Float.parseFloat(arg0) <= Float.parseFloat(arg1)); + } else if (args.get(0).getType().equals(typeLong) || args.get(1).getType().equals(typeLong)) { + result = (Long.parseLong(arg0) <= Long.parseLong(arg1)); + } else if (args.get(0).getType().equals(typeInt) || args.get(1).getType().equals(typeInt)) { + result = (Integer.parseInt(arg0) <= Integer.parseInt(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol and = new Symbol(Parser.AND, 2, Symbol.Type.INFIX, "&&", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeBoolean) || args.get(1).getType().equals(typeBoolean)) { + result = (Boolean.parseBoolean(arg0) && Boolean.parseBoolean(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol or = new Symbol(Parser.OR, 2, Symbol.Type.INFIX, "||", Symbol.Type.INFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + String arg1 = args.get(1).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeBoolean) || args.get(1).getType().equals(typeBoolean)) { + result = (Boolean.parseBoolean(arg0) || Boolean.parseBoolean(arg1)); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); + public static final Symbol neg = new Symbol(Parser.NEG, 1, Symbol.Type.PREFIX, "!", Symbol.Type.PREFIX, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + String arg0 = args.get(0).getSymbol().toString(); + boolean result = false; + if (args.get(0).getType().equals(typeBoolean)) { + result = !Boolean.parseBoolean(arg0); + } + if (result) { + return new Constant(true_); + } else { + return new Constant(false_); + } + } + }); public static final Symbol cons = new Symbol("cons", 2, Symbol.Type.PREFIX, "($x,$y)->$x.add(0, $y)", Symbol.Type.LAMBDA_WITH_SIDE_EFFECT, new int[] {1, 0}); public static final Symbol append = new Symbol("append", 2, Symbol.Type.PREFIX, "add", Symbol.Type.METHOD_WITH_SIDE_EFFECT); public static final Symbol remove = new Symbol("remove", 2, Symbol.Type.PREFIX, "remove", Symbol.Type.METHOD_WITH_SIDE_EFFECT); @@ -86,6 +358,8 @@ } }); public static final Symbol null_ = new Symbol("null", 0, Symbol.Type.PREFIX, "null", Symbol.Type.PREFIX); + public static final Symbol true_ = new Symbol("true", 0, Symbol.Type.PREFIX, "true", Symbol.Type.PREFIX); + public static final Symbol false_ = new Symbol("false", 0, Symbol.Type.PREFIX, "false", Symbol.Type.PREFIX); public static final Symbol cond = new Symbol("if", 3, Symbol.Type.PREFIX, new Symbol.IImplGenerator() { final int count[] = {0}; @Override @@ -108,21 +382,17 @@ count[0]++; return temp; } + }, new Symbol.ICalculator() { + @Override + public Constant calculate(List args) { + if (args.get(0).getSymbol().equals(true_)) { + return args.get(1); + } else if (args.get(0).getSymbol().equals(false_)) { + return args.get(2); + } + return null; + } }); - - - public static final Symbol mod = new Symbol("mod", 2, Symbol.Type.PREFIX, "%", Symbol.Type.INFIX); - public static final Symbol eq = new Symbol("eq", 2, Symbol.Type.PREFIX, "==", Symbol.Type.INFIX); - public static final Symbol neq = new Symbol("neq", 2, Symbol.Type.PREFIX, "!=", Symbol.Type.INFIX); - public static final Symbol gt = new Symbol("gt", 2, Symbol.Type.PREFIX, ">", Symbol.Type.INFIX); - public static final Symbol lt = new Symbol("lt", 2, Symbol.Type.PREFIX, "<", Symbol.Type.INFIX); - public static final Symbol ge = new Symbol("ge", 2, Symbol.Type.PREFIX, ">=", Symbol.Type.INFIX); - public static final Symbol le = new Symbol("le", 2, Symbol.Type.PREFIX, "<=", Symbol.Type.INFIX); - public static final Symbol and = new Symbol("and", 2, Symbol.Type.PREFIX, "&&", Symbol.Type.INFIX); - public static final Symbol or = new Symbol("or", 2, Symbol.Type.PREFIX, "||", Symbol.Type.INFIX); - public static final Symbol neg = new Symbol("neg", 1, Symbol.Type.PREFIX, "!", Symbol.Type.PREFIX); - public static final Symbol true_ = new Symbol("true", 0, Symbol.Type.PREFIX, "true", Symbol.Type.PREFIX); - public static final Symbol false_ = new Symbol("false", 0, Symbol.Type.PREFIX, "false", Symbol.Type.PREFIX); public static final Symbol pair = new Symbol("pair", -1, Symbol.Type.PREFIX, new Symbol.IImplGenerator() { @Override public String generate(Type type, Type[] childrenTypes, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) { @@ -195,6 +465,15 @@ div.setInverses(new Symbol[] {mul}); minus.setInverses(new Symbol[] {minus}); mod.setSignature(new Type[] {typeInt, null, null}); + eq.setSignature(new Type[] {typeBoolean, null, null}); + neq.setSignature(new Type[] {typeBoolean, null, null}); + gt.setSignature(new Type[] {typeBoolean, null, null}); + lt.setSignature(new Type[] {typeBoolean, null, null}); + ge.setSignature(new Type[] {typeBoolean, null, null}); + le.setSignature(new Type[] {typeBoolean, null, null}); + and.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); + or.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); + neg.setSignature(new Type[] {typeBoolean, typeBoolean}); cons.setInverses(new Symbol[] {head, tail}); cons.setSignature(new Type[] {typeList, null, typeList}); append.setSignature(new Type[] {typeList, typeList, null}); @@ -205,18 +484,9 @@ length.setSignature(new Type[] {typeInt, null}); get.setSignature(new Type[] {null, typeList, typeInt}); set.setSignature(new Type[] {typeList, typeList, typeInt, null}); - eq.setSignature(new Type[] {typeBoolean, null, null}); - neq.setSignature(new Type[] {typeBoolean, null, null}); - gt.setSignature(new Type[] {typeBoolean, null, null}); - lt.setSignature(new Type[] {typeBoolean, null, null}); - ge.setSignature(new Type[] {typeBoolean, null, null}); - le.setSignature(new Type[] {typeBoolean, null, null}); - and.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); - or.setSignature(new Type[] {typeBoolean, typeBoolean, typeBoolean}); - neg.setSignature(new Type[] {typeBoolean, typeBoolean}); + null_.setSignature(new Type[] {null}); true_.setSignature(new Type[] {typeBoolean}); false_.setSignature(new Type[] {typeBoolean}); - null_.setSignature(new Type[] {null}); pair.setSignature(new Type[] {typePair,null,null}); pair.setInverses(new Symbol[] {left, right}); left.setSignature(new Type[] {null, typePair}); @@ -277,17 +547,6 @@ addSymbol(div); addSymbol(minus); addSymbol(mod); - addSymbol(cons); - addSymbol(append); - addSymbol(remove); - addSymbol(head); - addSymbol(tail); - addSymbol(length); - addSymbol(contains); - addSymbol(get); - addSymbol(set); - addSymbol(nil); - addSymbol(cond); addSymbol(eq); addSymbol(neq); addSymbol(gt); @@ -297,9 +556,20 @@ addSymbol(and); addSymbol(or); addSymbol(neg); + addSymbol(cons); + addSymbol(append); + addSymbol(remove); + addSymbol(head); + addSymbol(tail); + addSymbol(length); + addSymbol(contains); + addSymbol(get); + addSymbol(set); + addSymbol(cond); + addSymbol(nil); + addSymbol(null_); addSymbol(true_); addSymbol(false_); - addSymbol(null_); addSymbol(pair); addSymbol(left); addSymbol(right); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java index f4d0e19..6cadc2d 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java @@ -15,17 +15,31 @@ protected ResourceHierarchy resourceHierarchy = null; protected List pathParams = null; - public ResourcePath(String resourceName) { - super(resourceName); + public ResourcePath(String fullResourceName) { + super(fullResourceName); this.parent = null; - this.resourceHierarchy = new ResourceHierarchy(null, resourceName); + this.resourceHierarchy = new ResourceHierarchy(null, fullResourceName); this.pathParams = new ArrayList<>(); } - public ResourcePath(ResourcePath parent, String resourceName) { - super(parent.toString() + "." + resourceName); + public ResourcePath(String fullResourceName, ResourceHierarchy resourceHierarchy) { + super(fullResourceName); + this.parent = null; + this.resourceHierarchy = resourceHierarchy; + this.pathParams = new ArrayList<>(); + } + + public ResourcePath(ResourcePath parent, String leafResourceName) { + super(parent.toString() + "." + leafResourceName); this.parent = parent; - this.resourceHierarchy = new ResourceHierarchy(parent.getResourceHierarchy(), resourceName); + this.resourceHierarchy = new ResourceHierarchy(parent.getResourceHierarchy(), leafResourceName); + this.pathParams = parent.getPathParams(); + } + + public ResourcePath(ResourcePath parent, String leafResourceName, ResourceHierarchy resourceHierarchy) { + super(parent.toString() + "." + leafResourceName); + this.parent = parent; + this.resourceHierarchy = resourceHierarchy; this.pathParams = parent.getPathParams(); } @@ -37,6 +51,14 @@ this.pathParams.add(exp); } + public ResourcePath(ResourcePath parent, Expression exp, ResourceHierarchy resourceHierarchy) { + super(parent.toString() + ".{" + exp + "}"); + this.parent = parent; + this.resourceHierarchy = resourceHierarchy; + this.pathParams = new ArrayList<>(parent.getPathParams()); + this.pathParams.add(exp); + } + public ResourcePath(ResourcePath another) { super(another.name); this.parent = another.parent; @@ -52,7 +74,7 @@ this.resourceHierarchy = resourceHierarchy; } - public String getResourceName() { + public String getLeafResourceName() { return resourceHierarchy.getResourceName(); } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java index ce8c581..15e3194 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -163,7 +163,7 @@ @Override public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - String resource = target.getResource().getResourceName(); + String resource = target.getResource().getLeafResourceName(); Parameter curStateParam = curStateParams.get(resource); if (curStateParam == null) { curStateParam = new Parameter("cur" + resource); @@ -174,7 +174,7 @@ @Override public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - String resource = target.getResource().getResourceName(); + String resource = target.getResource().getLeafResourceName(); Parameter nextStateParam = nextStateParams.get(resource); if (nextStateParam == null) { nextStateParam = new Parameter("next" + target); @@ -185,7 +185,7 @@ @Override public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { - String resource = target.getResourceName(); + String resource = target.getLeafResourceName(); Parameter curStateParam = curStateParams.get(resource); if (curStateParam == null) { curStateParam = new Parameter("cur" + resource); @@ -194,26 +194,26 @@ return curStateParam; } }; - return deriveUpdateExpressionOf(targetMember, defaultStateAccessor); + return deriveUpdateExpressionOf(targetMember, defaultStateAccessor).getKey(); } /** * Derive the state update calculation of the target channel member with a given resource push/pull state accessor. * @param targetMember a channel member whose state is to be updated * @param stateAccessor a push/pull resource state accessor - * @return the derived update calculation + * @return the derived update calculation and the unified message * @throws ParameterizedIdentifierIsFutureWork * @throws ResolvingMultipleDefinitionIsFutureWork * @throws InvalidMessage * @throws UnificationFailed * @throws ValueUndefined */ - public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor) + public Map.Entry deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { return deriveUpdateExpressionOf(targetMember, stateAccessor, null); } - public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, Map inputResourceToStateAccessor) + public Map.Entry deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, Map inputResourceToStateAccessor) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { if (!getOutputChannelMembers().contains(targetMember)) return null; @@ -229,14 +229,35 @@ unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); } } - return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); + return new AbstractMap.SimpleEntry<>(targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage), unifiedMessage); + } + + /** + * Derive the state update calculation of the target channel member with a message and a given resource push/pull state accessor. + * @param targetMember a channel member whose state is to be updated + * @param message a message on the channel + * @param stateAccessor a push/pull resource state accessor + * @return the derived update calculation + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public Expression deriveUpdateExpressionOf(ChannelMember targetMember, Term message, IResourceStateAccessor stateAccessor) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + if (!getOutputChannelMembers().contains(targetMember)) return null; + + // Calculate the next state of target resource from the unified message and the current resource state + Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetMember, targetMember); + return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, message); } /** * Fill outside resource paths with a given resource push/pull state accessor. + * @param targetMember a channel member whose state is to be updated * @param stateAccessor a push/pull resource state accessor - * @param resourcePaths a container to be returned with filled outside resource paths - * @return the derived update calculation + * @return map from a depending channel member to the pair of the filled resource path and the set of the depended channel members * @throws ParameterizedIdentifierIsFutureWork * @throws ResolvingMultipleDefinitionIsFutureWork * @throws InvalidMessage @@ -254,19 +275,19 @@ Map>> resourcePaths = new HashMap<>(); // Calculate unified message constraints from input and reference state transitions - Map> substitutedPositionsFromChannels = new HashMap<>(); - Term unifiedMessage = calcUnifiedMessage(targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsFromChannels); + Map> substitutedPositionsInMessageFromChannels = new HashMap<>(); + Term unifiedMessage = calcUnifiedMessage(targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsInMessageFromChannels); // Fill outside resource paths if (unifiedMessage != null) { for (ChannelMember cm: getInputChannelMembers()) { if (cm.isOutside()) { - Set dependingVarPos = new HashSet<>(); - ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPos); + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPosInMessage); Set dependingChannelMembers = new HashSet<>(); - for (ChannelMember otherCm: substitutedPositionsFromChannels.keySet()) { - for (Position otherPos: substitutedPositionsFromChannels.get(otherCm)) { - for (Position thisPos: dependingVarPos) { + for (ChannelMember otherCm: substitutedPositionsInMessageFromChannels.keySet()) { + for (Position otherPos: substitutedPositionsInMessageFromChannels.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { if (thisPos.isAncestorOf(otherPos)) { dependingChannelMembers.add(otherCm); break; @@ -275,17 +296,17 @@ if (dependingChannelMembers.contains(otherCm)) break; } } - resourcePaths.put(cm, new AbstractMap.SimpleEntry(filledResPath, dependingChannelMembers)); + resourcePaths.put(cm, new AbstractMap.SimpleEntry<>(filledResPath, dependingChannelMembers)); } } for (ChannelMember cm: getReferenceChannelMembers()) { if (cm.isOutside()) { - Set dependingVarPos = new HashSet<>(); - ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPos); + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPosInMessage); Set dependingChannelMembers = new HashSet<>(); - for (ChannelMember otherCm: substitutedPositionsFromChannels.keySet()) { - for (Position otherPos: substitutedPositionsFromChannels.get(otherCm)) { - for (Position thisPos: dependingVarPos) { + for (ChannelMember otherCm: substitutedPositionsInMessageFromChannels.keySet()) { + for (Position otherPos: substitutedPositionsInMessageFromChannels.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { if (thisPos.isAncestorOf(otherPos)) { dependingChannelMembers.add(otherCm); break; @@ -294,17 +315,17 @@ if (dependingChannelMembers.contains(otherCm)) break; } } - resourcePaths.put(cm, new AbstractMap.SimpleEntry(filledResPath, dependingChannelMembers)); + resourcePaths.put(cm, new AbstractMap.SimpleEntry<>(filledResPath, dependingChannelMembers)); } } for (ChannelMember cm: getOutputChannelMembers()) { if (cm.isOutside()) { - Set dependingVarPos = new HashSet<>(); - ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPos); + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = fillOutsideResourcePath(cm.getResource(), unifiedMessage, targetMember.getStateTransition().getMessageExpression(), dependingVarPosInMessage); Set dependingChannelMembers = new HashSet<>(); - for (ChannelMember otherCm: substitutedPositionsFromChannels.keySet()) { - for (Position otherPos: substitutedPositionsFromChannels.get(otherCm)) { - for (Position thisPos: dependingVarPos) { + for (ChannelMember otherCm: substitutedPositionsInMessageFromChannels.keySet()) { + for (Position otherPos: substitutedPositionsInMessageFromChannels.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { if (thisPos.isAncestorOf(otherPos)) { dependingChannelMembers.add(otherCm); break; @@ -313,46 +334,93 @@ if (dependingChannelMembers.contains(otherCm)) break; } } - resourcePaths.put(cm, new AbstractMap.SimpleEntry(filledResPath, dependingChannelMembers)); + resourcePaths.put(cm, new AbstractMap.SimpleEntry<>(filledResPath, dependingChannelMembers)); } } } return resourcePaths; } - + + public Map> getMemberDependency() { + Map> dependency = new HashMap<>(); + + // Collect depended channel members and their positions in the message + Map> substitutedPositionsInMessage = getDependedChannelMembersAndTheirPositionsInMessage(); + + // Resolve dependency for each outside resource path + if (substitutedPositionsInMessage != null) { + for (ChannelMember cm: getInputChannelMembers()) { + if (cm.isOutside()) { + Set dependingVarPosInMessage = getPossitionsInMessageThatChannelMemberDependsOn(cm.getResource(), cm.getStateTransition().getMessageExpression()); + Set dependingChannelMembers = new HashSet<>(); + for (ChannelMember otherCm: substitutedPositionsInMessage.keySet()) { + for (Position otherPos: substitutedPositionsInMessage.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { + if (thisPos.isAncestorOf(otherPos)) { + dependingChannelMembers.add(otherCm); + break; + } + } + if (dependingChannelMembers.contains(otherCm)) break; + } + } + dependency.put(cm, dependingChannelMembers); + } + } + for (ChannelMember cm: getReferenceChannelMembers()) { + if (cm.isOutside()) { + Set dependingVarPosInMessage = getPossitionsInMessageThatChannelMemberDependsOn(cm.getResource(), cm.getStateTransition().getMessageExpression()); + Set dependingChannelMembers = new HashSet<>(); + for (ChannelMember otherCm: substitutedPositionsInMessage.keySet()) { + for (Position otherPos: substitutedPositionsInMessage.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { + if (thisPos.isAncestorOf(otherPos)) { + dependingChannelMembers.add(otherCm); + break; + } + } + if (dependingChannelMembers.contains(otherCm)) break; + } + } + dependency.put(cm, dependingChannelMembers); + } + } + for (ChannelMember cm: getOutputChannelMembers()) { + if (cm.isOutside()) { + Set dependingVarPosInMessage = getPossitionsInMessageThatChannelMemberDependsOn(cm.getResource(), cm.getStateTransition().getMessageExpression()); + Set dependingChannelMembers = new HashSet<>(); + for (ChannelMember otherCm: substitutedPositionsInMessage.keySet()) { + for (Position otherPos: substitutedPositionsInMessage.get(otherCm)) { + for (Position thisPos: dependingVarPosInMessage) { + if (thisPos.isAncestorOf(otherPos)) { + dependingChannelMembers.add(otherCm); + break; + } + } + if (dependingChannelMembers.contains(otherCm)) break; + } + } + dependency.put(cm, dependingChannelMembers); + } + } + } + return dependency; + } + private Term calcUnifiedMessage(ChannelMember targetMember, IResourceStateAccessor stateAccessor, - Map inputResourceToStateAccessor, Map> substitutedPositionsFromChannels) + Map inputResourceToStateAccessor, Map> substitutedPositionsInMessageFromChannels) throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork, UnificationFailed { Set messageConstraints = new HashSet<>(); // Calculate message constraints from input state transitions for (ChannelMember inputMember: getInputChannelMembers()) { - Expression curInputStateAccessor = null; - Expression nextInputStateAccessor = null; - if (inputResourceToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputMember, targetMember); - nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputMember, targetMember); - } else { - curInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getCurrentStateAccessorFor(inputMember, targetMember); - nextInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getNextStateAccessorFor(inputMember, targetMember); - } - Set substitutedPositions = new HashSet<>(); - Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor, substitutedPositions); - if (substitutedPositions.size() > 0) substitutedPositionsFromChannels.put(inputMember, substitutedPositions); + Expression messageConstraintByInput = calcMessageConstraintForInputMember(inputMember, targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsInMessageFromChannels); messageConstraints.add((Term) messageConstraintByInput); } // Calculate message constraints from reference state transitions for (ChannelMember referenceMember: getReferenceChannelMembers()) { - Expression curInputStateAccessor = null; - if (inputResourceToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceMember, targetMember); - } else { - curInputStateAccessor = inputResourceToStateAccessor.get(referenceMember).getCurrentStateAccessorFor(referenceMember, targetMember); - } - Set substitutedPositions = new HashSet<>(); - Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, substitutedPositions); - if (substitutedPositions.size() > 0) substitutedPositionsFromChannels.put(referenceMember, substitutedPositions); + Expression messageConstraintByReference = calcMessageConstraintForReferenceMember(referenceMember, targetMember, stateAccessor, inputResourceToStateAccessor, substitutedPositionsInMessageFromChannels); messageConstraints.add((Term) messageConstraintByReference); } @@ -371,7 +439,93 @@ return unifiedMessage; } - private ResourcePath fillOutsideResourcePath(ResourcePath resource, Term unifiedMessage, Expression messageTerm, Set dependingVarPos) + public Expression calcMessageConstraintForInputMember(ChannelMember inputMember, ChannelMember targetMember, IResourceStateAccessor stateAccessor, + Map inputResourceToStateAccessor, Map> substitutedPositionsInMessageFromChannels) + throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork { + Expression curInputStateAccessor = null; + Expression nextInputStateAccessor = null; + if (inputResourceToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputMember, targetMember); + nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputMember, targetMember); + } else { + curInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getCurrentStateAccessorFor(inputMember, targetMember); + nextInputStateAccessor = inputResourceToStateAccessor.get(inputMember).getNextStateAccessorFor(inputMember, targetMember); + } + Set substitutedPositionsInMessage = new HashSet<>(); + Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor, substitutedPositionsInMessage); + if (substitutedPositionsInMessage.size() > 0) substitutedPositionsInMessageFromChannels.put(inputMember, substitutedPositionsInMessage); + return messageConstraintByInput; + } + + public Expression calcMessageConstraintForReferenceMember(ChannelMember referenceMember, ChannelMember targetMember, IResourceStateAccessor stateAccessor, + Map inputResourceToStateAccessor, Map> substitutedPositionsInMessageFromChannels) + throws InvalidMessage, ResolvingMultipleDefinitionIsFutureWork { + Expression curInputStateAccessor = null; + if (inputResourceToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceMember, targetMember); + } else { + curInputStateAccessor = inputResourceToStateAccessor.get(referenceMember).getCurrentStateAccessorFor(referenceMember, targetMember); + } + Set substitutedPositions = new HashSet<>(); + Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, substitutedPositions); + if (substitutedPositions.size() > 0) substitutedPositionsInMessageFromChannels.put(referenceMember, substitutedPositions); + return messageConstraintByReference; + } + + /** + * Get depended channel members and their positions in the message. + * + * @return depended channel members and their positions in the message + */ + private Map> getDependedChannelMembersAndTheirPositionsInMessage() { + Map> channelMembersMessageDependsOn = new HashMap<>(); + // Collect channel members that the message depends on from input state transitions + for (ChannelMember inputMember: getInputChannelMembers()) { + Set substitutedPositionsInMessage = new HashSet<>(); + Expression messageTerm = inputMember.getStateTransition().getMessageExpression(); + Expression curStateTerm = inputMember.getStateTransition().getCurStateExpression(); + Expression nextStateTerm = inputMember.getStateTransition().getNextStateExpression(); + HashMap messageVars = messageTerm.getVariables(); + for (Entry varEnt: messageVars.entrySet()) { + Variable var = varEnt.getValue(); + if (curStateTerm.getVariables().values().contains(var) || nextStateTerm.getVariables().values().contains(var)) { + if (messageTerm instanceof Term) { + substitutedPositionsInMessage.add(varEnt.getKey()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + substitutedPositionsInMessage.add(new Position()); + } + } + } + } + if (substitutedPositionsInMessage.size() > 0) channelMembersMessageDependsOn.put(inputMember, substitutedPositionsInMessage); + } + + // Collect channel members that the message depends on from reference state transitions + for (ChannelMember referenceMember: getReferenceChannelMembers()) { + Set substitutedPositionsInMessage = new HashSet<>(); + Expression messageTerm = referenceMember.getStateTransition().getMessageExpression(); + Expression curStateTerm = referenceMember.getStateTransition().getCurStateExpression(); + Expression nextStateTerm = referenceMember.getStateTransition().getNextStateExpression(); + HashMap messageVars = messageTerm.getVariables(); + for (Entry varEnt: messageVars.entrySet()) { + Variable var = varEnt.getValue(); + if (curStateTerm.getVariables().values().contains(var) || nextStateTerm.getVariables().values().contains(var)) { + if (messageTerm instanceof Term) { + substitutedPositionsInMessage.add(varEnt.getKey()); + } else if (messageTerm instanceof Variable) { + if (messageTerm.equals(var)) { + substitutedPositionsInMessage.add(new Position()); + } + } + } + } + if (substitutedPositionsInMessage.size() > 0) channelMembersMessageDependsOn.put(referenceMember, substitutedPositionsInMessage); + } + return channelMembersMessageDependsOn; + } + + public ResourcePath fillOutsideResourcePath(ResourcePath resource, Term unifiedMessage, Expression messageTerm, Set dependingVarPosInMessage) throws ResolvingMultipleDefinitionIsFutureWork { ResourcePath filledResourcePath = new ResourcePath(resource); @@ -383,7 +537,7 @@ Expression valueCalc = unifiedMessage.getSubTerm(varPos); if (valueCalc != null) { if (bindings.get(var) != null) throw new ResolvingMultipleDefinitionIsFutureWork(); - bindings.put(var, new AbstractMap.SimpleEntry(varPos, valueCalc)); + bindings.put(var, new AbstractMap.SimpleEntry<>(varPos, valueCalc)); } } @@ -391,25 +545,51 @@ for (int i = 0; i < filledResourcePath.getPathParams().size(); i++) { Expression pathParam = dstParams.get(i); if (pathParam instanceof Variable) { - dstParams.set(i, bindings.get((Variable) pathParam).getValue()); - dependingVarPos.add(bindings.get((Variable) pathParam).getKey()); - } else { + dstParams.set(i, bindings.get((Variable) pathParam).getValue()); // Replace a path parameter with a value in the unified message. + dependingVarPosInMessage.add(bindings.get((Variable) pathParam).getKey()); // The position of the replaced variable in the message. + } else if (pathParam instanceof Term) { Map pathParamVars = ((Term) pathParam).getVariables(); for (Variable var: bindings.keySet()) { - if (pathParamVars.values().contains(var)) { - pathParam = ((Term) pathParam).substitute(var, bindings.get(var).getValue()); - dependingVarPos.add(bindings.get((Variable) var).getKey()); + if (pathParamVars.values().contains(var)) { // var is a subterm of a path parameter + pathParam = ((Term) pathParam).substitute(var, bindings.get(var).getValue()); // Substitute a value in the unified message to var. + dependingVarPosInMessage.add(bindings.get((Variable) var).getKey()); // The position of the replaced variable in the message. } } if (!(pathParam instanceof Constant)) { pathParam = ((Term) pathParam).reduce(); } - dstParams.set(i, pathParam); + dstParams.set(i, pathParam); // Replace a path parameter with the substituted term. } } return filledResourcePath; } + private Set getPossitionsInMessageThatChannelMemberDependsOn(ResourcePath resourcePath, Expression messageTerm) { + Set dependingVarPosInMessage = new HashSet<>(); + Map messageVars = messageTerm.getVariables(); + for (Expression pathParam: resourcePath.getPathParams()) { + if (pathParam instanceof Variable) { + for (Entry messageVarEnt: messageVars.entrySet()) { + Variable var = messageVarEnt.getValue(); + Position varPos = messageVarEnt.getKey(); + if (pathParam.equals(var)) { + dependingVarPosInMessage.add(varPos); + } + } + } else if (pathParam instanceof Term) { + Map pathParamVars = ((Term) pathParam).getVariables(); + for (Entry messageVarEnt: messageVars.entrySet()) { + Variable var = messageVarEnt.getValue(); + Position varPos = messageVarEnt.getKey(); + if (pathParamVars.values().contains(var)) { + dependingVarPosInMessage.add(varPos); + } + } + } + } + return dependingVarPosInMessage; + } + @Override public String toString() { String channelSource = "channel " + getChannelName() + " {\n"; diff --git a/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannel.java b/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannel.java index 581d31e..2fb57ee 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannel.java @@ -32,24 +32,24 @@ // channelMember.setStateTransition(st); super.addChannelMemberAsInput(channelMember); if (formula != null && getInputChannelMembers().size() > 1) { - formula += " " + defaultOperator + " " + channelMember.getResource().getResourceName(); + formula += " " + defaultOperator + " " + channelMember.getResource().getLeafResourceName(); if (formulaRhs != null) { if (formulaRhs instanceof Variable) { Term newTerm = new Term(defaultOperator); newTerm.addChild(formulaRhs); - newTerm.addChild(new Variable(channelMember.getResource().getResourceName()), true); + newTerm.addChild(new Variable(channelMember.getResource().getLeafResourceName()), true); formulaRhs = newTerm; } else if (formulaRhs instanceof Term) { Term newTerm = new Term(defaultOperator); newTerm.addChild(formulaRhs); - newTerm.addChild(new Variable(channelMember.getResource().getResourceName())); + newTerm.addChild(new Variable(channelMember.getResource().getLeafResourceName())); formulaRhs = newTerm; } } } else { if (formula == null) formula = ""; - formula += channelMember.getResource().getResourceName(); - formulaRhs = new Variable(channelMember.getResource().getResourceName()); + formula += channelMember.getResource().getLeafResourceName(); + formulaRhs = new Variable(channelMember.getResource().getLeafResourceName()); } if (formulaRhs != null) { setFormulaTerm(formulaRhs); @@ -63,8 +63,8 @@ super.addChannelMemberAsOutput(channelMember); if (getOutputChannelMembers().size() == 1) { if (formula == null) formula = ""; - if (!formula.contains("==")) { - formula = channelMember.getResource().getResourceName() + " == " + formula; + if (!formula.contains("=")) { + formula = channelMember.getResource().getLeafResourceName() + " = " + formula; } } if (formulaRhs != null) { @@ -96,7 +96,7 @@ Map resToNextVar = new HashMap<>(); for (ChannelMember cm: this.getInputChannelMembers()) { ResourcePath id = cm.getResource(); - String resName = id.getResourceName(); + String resName = id.getLeafResourceName(); Variable curVar = new Variable(resName + "1"); Variable nextVar = new Variable(resName + "2"); curStates.put(id, curVar); @@ -134,7 +134,7 @@ for (ChannelMember cm: getOutputChannelMembers()) { ResourcePath id = cm.getResource(); StateTransition st = new StateTransition(); - String resName = id.getResourceName(); + String resName = id.getLeafResourceName(); Variable curVar = new Variable(resName + "1"); st.setCurStateExpression(curVar); st.setNextStateExpression(rhs); diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index 126b47b..bc6429b 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -62,12 +62,23 @@ public static final String MUL = "*"; public static final String SUB = "-"; public static final String DIV = "/"; + public static final String MOD = "%"; public static final String MINUS = "-"; + public static final String EQ = "=="; + public static final String NEQ = "!="; + public static final String GT = ">"; + public static final String LT = "<"; + public static final String GE = ">="; + public static final String LE = "<="; + public static final String AND = "&&"; + public static final String OR = "||"; + public static final String NEG = "!"; public static final String ADD_REGX = "\\+"; public static final String MUL_REGX = "\\*"; public static final String SUB_REGX = "\\-"; public static final String DIV_REGX = "/"; - public static final String EQUALS = "=="; + public static final String OR_REGX = "\\|\\|"; + public static final String EQUALS = "="; public static final String ASSIGNMENT = "="; public static final String COMMA = ","; public static final String COLON = ":"; @@ -265,30 +276,33 @@ ArrayList operators = new ArrayList<>(); String operator = null; for (;;) { - String leftBracketOrMinus = stream.next(); - if (leftBracketOrMinus.equals(LEFT_BRACKET)) { + String leftBracketOrMinusOrNeg = stream.next(); + if (leftBracketOrMinusOrNeg.equals(LEFT_BRACKET)) { Expression exp = parseTerm(stream, model); String rightBracket = stream.next(); if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); expressions.add(exp); - } else if (leftBracketOrMinus.equals(LEFT_CURLY_BRACKET)) { + } else if (leftBracketOrMinusOrNeg.equals(LEFT_CURLY_BRACKET)) { Expression exp = parseJsonTerm(stream, model); String rightBracket = stream.next(); if (!rightBracket.equals(RIGHT_CURLY_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); expressions.add(exp); - } else if (leftBracketOrMinus.equals(LEFT_SQUARE_BRACKET)) { + } else if (leftBracketOrMinusOrNeg.equals(LEFT_SQUARE_BRACKET)) { Expression exp = parseListTerm(stream, model); String rightBracket = stream.next(); if (!rightBracket.equals(RIGHT_SQUARE_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); expressions.add(exp); } else { - Symbol minus = null; + Symbol minusOrNeg = null; String symbolName = null; - if (leftBracketOrMinus.equals(MINUS)) { - minus = DataTransferModel.minus; // not sub + if (leftBracketOrMinusOrNeg.equals(MINUS)) { + minusOrNeg = DataTransferModel.minus; // not sub + symbolName = stream.next(); + } else if (leftBracketOrMinusOrNeg.equals(NEG)) { + minusOrNeg = DataTransferModel.neg; symbolName = stream.next(); } else { - symbolName = leftBracketOrMinus; + symbolName = leftBracketOrMinusOrNeg; } Expression exp = null; if (stream.checkNext() != null && stream.checkNext().equals(LEFT_BRACKET)) { @@ -332,16 +346,19 @@ } else { exp = new Constant(symbolName, DataTransferModel.typeInt); } + } else if (symbolName.startsWith("\"") && symbolName.endsWith("\"")) { + // a string value + exp = new Constant(symbolName, DataTransferModel.typeString); } else { // a variable exp = parseVariable(stream, model, symbolName); } } } - if (minus != null) { - Term minusTerm = new Term(minus); - minusTerm.addChild(exp); - expressions.add(minusTerm); + if (minusOrNeg != null) { + Term minusOrNegTerm = new Term(minusOrNeg); + minusOrNegTerm.addChild(exp); + expressions.add(minusOrNegTerm); } else { expressions.add(exp); } @@ -361,6 +378,36 @@ } else if (operator.equals(DIV)) { operators.add(DataTransferModel.div); stream.next(); + } else if (operator.equals(MOD)) { + operators.add(DataTransferModel.mod); + stream.next(); + } else if (operator.equals(EQ)) { + operators.add(DataTransferModel.eq); + stream.next(); + } else if (operator.equals(NEQ)) { + operators.add(DataTransferModel.neq); + stream.next(); + } else if (operator.equals(GT)) { + operators.add(DataTransferModel.gt); + stream.next(); + } else if (operator.equals(LT)) { + operators.add(DataTransferModel.lt); + stream.next(); + } else if (operator.equals(GE)) { + operators.add(DataTransferModel.ge); + stream.next(); + } else if (operator.equals(LE)) { + operators.add(DataTransferModel.le); + stream.next(); + } else if (operator.equals(AND)) { + operators.add(DataTransferModel.and); + stream.next(); + } else if (operator.equals(OR)) { + operators.add(DataTransferModel.or); + stream.next(); + } else if (operator.equals(NEG)) { + operators.add(DataTransferModel.neg); + stream.next(); } else if (operator.equals(DOT)) { // json accessor Expression exp = expressions.remove(0); @@ -408,7 +455,9 @@ int i = 1; for (Symbol op: operators) { Expression second = expressions.get(i); - if (op.getName().equals(MUL) || op.getName().equals(DIV)) { + if (op.getName().equals(MUL) || op.getName().equals(DIV) || op.getName().equals(MOD) + || op.getName().equals(EQ) || op.getName().equals(NEQ) || op.getName().equals(GT) || op.getName().equals(LT) + || op.getName().equals(GE) || op.getName().equals(LE) || op.getName().equals(AND) || op.getName().equals(OR)) { Term term = new Term(op); term.addChild(first); term.addChild(second); @@ -560,7 +609,7 @@ } public static class TokenStream { - private ArrayList> tokens = new ArrayList<>(); + private ArrayList> tokens = new ArrayList<>(); private ArrayList lines = new ArrayList<>(); private int line = 0; private int n = 0; @@ -588,15 +637,45 @@ splitBy( splitBy( splitBy( - Arrays.asList(line.split("[ \t]")), - ADD, - ADD_REGX), - MUL, - MUL_REGX), - SUB, - SUB_REGX), - DIV, - DIV_REGX), + splitBy( + splitBy( + splitBy( + splitBy( + splitBy( + splitBy( + splitBy( + splitBy( + splitBy( + splitBy( + line.split("[ \t]"), + ADD, + ADD_REGX), + MUL, + MUL_REGX), + SUB, + SUB_REGX), + DIV, + DIV_REGX), + MOD, + MOD), + EQ, + EQ), + NEQ, + NEQ), + GE, + GE), + LE, + LE), + GT, + GT), + LT, + LT), + AND, + AND), + OR, + OR_REGX), + NEG, + NEG), DOT, DOT_REGX), COMMA, @@ -618,24 +697,36 @@ RIGHT_SQUARE_BRACKET, RIGHT_SQUARE_BRACKET_REGX)); } - - private ArrayList splitBy(final List tokens, final String delimiter, final String delimiterRegx) { - ArrayList newTokens = new ArrayList<>(); + + private ArrayList splitBy(String[] tokens, final String delimiter, final String delimiterRegx) { + ArrayList newTokens = new ArrayList<>(); for (String token: tokens) { - String[] splitTokens = token.split(delimiterRegx); - boolean fFirstToken = true; - for (String t: splitTokens) { - if (!fFirstToken) { - newTokens.add(delimiter); + newTokens.add(new Token(token)); + } + return splitBy(newTokens, delimiter, delimiterRegx); + } + + private ArrayList splitBy(final List tokens, final String delimiter, final String delimiterRegx) { + ArrayList newTokens = new ArrayList<>(); + for (Token token: tokens) { + if (token.isAtomic()) { + newTokens.add(token); + } else { + String[] splitTokens = token.split(delimiterRegx); + boolean fFirstToken = true; + for (String t: splitTokens) { + if (!fFirstToken) { + newTokens.add(new Token(delimiter, true)); + } + if (t.length() > 0) { + newTokens.add(new Token(t)); + } + fFirstToken = false; } - if (t.length() > 0) { - newTokens.add(t); + while (token.endsWith(delimiter)) { + newTokens.add(new Token(delimiter, true)); + token = token.substring(0, token.length() - 1); } - fFirstToken = false; - } - while (token.endsWith(delimiter)) { - newTokens.add(delimiter); - token = token.substring(0, token.length() - 1); } } return newTokens; @@ -648,7 +739,7 @@ n = 0; if (line >= tokens.size()) return null; } - String token = tokens.get(line).get(n); + String token = tokens.get(line).get(n).getTokenStr(); n++; return token; } @@ -660,7 +751,7 @@ n = 0; if (line >= tokens.size()) return null; } - return tokens.get(line).get(n); + return tokens.get(line).get(n).getTokenStr(); } public boolean hasNext() { @@ -685,4 +776,42 @@ return text; } } + + public static class Token { + String token; + boolean isAtomic = false; + + public Token(String token) { + this.token = token; + } + + public Token(String token, boolean isAtomic) { + this.token = token; + this.isAtomic = isAtomic; + } + + public String getTokenStr() { + return token; + } + + public boolean isAtomic() { + return isAtomic; + } + + public String[] split(String delimiterRegx) { + return token.split(delimiterRegx); + } + + public boolean endsWith(String delimiter) { + return token.endsWith(delimiter); + } + + public int length() { + return token.length(); + } + + public Token substring(int beginIdx, int endIdx) { + return new Token(token.substring(beginIdx, endIdx)); + } + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java new file mode 100644 index 0000000..9fd4993 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java @@ -0,0 +1,134 @@ +package simulator; + +import java.util.Map; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.DataTransferChannel; + +public class ChannelState { + private DataTransferChannel channel; + private ReferenceStructure referenceStructure; + + public ChannelState(DataTransferChannel channel) { + this.channel = channel; + } + + public DataTransferChannel getChannel() { + return channel; + } + + public Map getDependingParamAndValues(List channelValues) { + if (referenceStructure == null) { + return null; + } + return referenceStructure.getDependingParamAndValues(channelValues); + } + + public List> getDependedChannelSelectorValues(Expression dependingVariable, Expression itsValue) { + if (referenceStructure == null) { + return null; + } + Map dependingVarToVal = new HashMap<>(); + dependingVarToVal.put(dependingVariable, itsValue); + return referenceStructure.getDependedChannelSelectorValues(dependingVarToVal); + } + + public List> getDependedChannelSelectorValues(Map dependingVarToVal) { + if (referenceStructure == null) { + return null; + } + return referenceStructure.getDependedChannelSelectorValues(dependingVarToVal); + } + + public void addDependingParamAndValue(List channelValues, Expression dependingVariable, Expression itsValue) { + if (referenceStructure == null) { + referenceStructure = new ReferenceStructure(); + } + referenceStructure.addDependingParamAndValue(channelValues, dependingVariable, itsValue); + } + + private static class ReferenceStructure { + private Map dependingParamAndValues = null; + private Map referenceStructure; + + public Map getDependentParamAndValues() { + return dependingParamAndValues; + } + + public Map getDependingParamAndValues(List channelValues) { + ReferenceStructure subStructure = this; + for (Constant chVal: channelValues) { + if (subStructure.getDependentParamAndValues() == null) { + subStructure = subStructure.getReferenceStructure(chVal); + } else { + return null; + } + } + return subStructure.getDependentParamAndValues(); + } + + public List> getDependedChannelSelectorValues(Map dependingVarToVal) { + List> channelValuesList = new ArrayList<>(); + if (dependingParamAndValues != null) { + boolean doesMatch = true; + for (Expression dependingVariable: dependingVarToVal.keySet()) { + if (dependingParamAndValues.keySet().contains(dependingVariable)) { + if (!dependingParamAndValues.get(dependingVariable).equals(dependingVarToVal.get(dependingVariable))) { + doesMatch = false; + } + } + } + if (doesMatch) { + List> chValsList = new ArrayList<>(); + chValsList.add(new ArrayList<>()); + return chValsList; + } else { + return null; + } + } else { + for (Constant chVal: referenceStructure.keySet()) { + List> chValsList = referenceStructure.get(chVal).getDependedChannelSelectorValues(dependingVarToVal); + if (chValsList != null) { + for (List chVals: chValsList) { + chVals.add(0, chVal); + channelValuesList.add(chVals); + } + } + } + } + return channelValuesList; + } + + public void addDependingParamAndValue(Expression dependingVariable, Expression itsValue) { + if (dependingParamAndValues == null) { + dependingParamAndValues = new HashMap<>(); + } + dependingParamAndValues.put(dependingVariable, itsValue); + } + + public void addDependingParamAndValue(List channelValues, Expression dependingVariable, Expression itsValue) { + ReferenceStructure subStructure = this; + for (Constant chVal: channelValues) { + if (subStructure.referenceStructure == null) { + subStructure.referenceStructure = new HashMap<>(); + } + ReferenceStructure nextStructure = subStructure.referenceStructure.get(chVal); + if (nextStructure == null) { + nextStructure = new ReferenceStructure(); + subStructure.referenceStructure.put(chVal, nextStructure); + } + subStructure = nextStructure; + } + subStructure.addDependingParamAndValue(dependingVariable, itsValue); + } + + public ReferenceStructure getReferenceStructure(Constant channelParam) { + return referenceStructure.get(channelParam); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java new file mode 100644 index 0000000..13df0a0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -0,0 +1,384 @@ +package simulator; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.Position; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; + +public class Event { + private DataTransferChannel channel; + private Expression message; + private boolean isInput = false; + private ResourcePath inputResourcePath = null; + + private List> channelSelectorAndValues = new ArrayList<>(); + private Map dependingParameters = new HashMap<>(); + private Set inputResources = new HashSet<>(); + private Set outputResources = new HashSet<>(); + private Set succEvents = new HashSet<>(); + private Map> channelSelectorToInputResourcePathParam = new HashMap<>(); + private Map> channelSelectorToOutputResourcePathParam = new HashMap<>(); + + public Event(DataTransferChannel channel, Expression message, ResourcePath outputResPath, Resource outputResource) { + this.channel = channel; + this.message = message; + this.isInput = true; + this.outputResources.add(outputResource); + connectChannelSelectorAndPathParameters(); + + // Extract channel parameters from the output resource. + List channelSelectors = channel.getAllSelectors(); + for (Selector sel: channelSelectors) { + int paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath); + Resource ancestor = outputResource; + int idx = outputResPath.getPathParams().size(); + while (ancestor != null) { + if (ancestor.getResourceHierarchy().getNumParameters() > 0) { + idx--; + if (idx == paramIdx) break; + } + ancestor = ancestor.getParent(); + } + channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter())); + } + } + + public Event(DataTransferChannel channel, ResourcePath inputResPath, Resource inputResource) { + this.channel = channel; + this.isInput = false; + this.inputResourcePath = inputResPath; + this.inputResources.add(inputResource); + connectChannelSelectorAndPathParameters(); + + // Extract channel parameters from the input resource. + List channelSelectors = channel.getAllSelectors(); + for (Selector sel: channelSelectors) { + if (inputResPath != null) { + Integer paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); + if (paramIdx != null) { + Resource ancestor = inputResource; + int idx = inputResPath.getPathParams().size(); + while (ancestor != null) { + if (ancestor.getResourceHierarchy().getNumParameters() > 0) { + idx--; + if (idx == paramIdx) break; + } + ancestor = ancestor.getParent(); + } + channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter())); + } + } + } + } + + public Event(DataTransferChannel channel, ResourcePath inputResPath, Resource inputResource, List channelSelectorValues, Map dependingVarToVal) { + this.channel = channel; + this.isInput = false; + this.inputResourcePath = inputResPath; + this.inputResources.add(inputResource); + connectChannelSelectorAndPathParameters(); + + // Extract channel parameters from the input resource. + List channelSelectors = channel.getAllSelectors(); + for (int i = 0; i < channelSelectors.size(); i++) { + Selector sel = channelSelectors.get(i); + channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, channelSelectorValues.get(i))); + } + this.dependingParameters = dependingVarToVal; + } + + private void connectChannelSelectorAndPathParameters() { + List channelSelectors = channel.getAllSelectors(); + for (Selector sel: channelSelectors) { + for (ResourcePath resPath: channel.getInputResources()) { + int paramIdx = resPath.getPathParams().indexOf(sel.getExpression()); + if (paramIdx >= 0) { + Map pathToIdx = channelSelectorToInputResourcePathParam.get(sel); + if (pathToIdx == null) { + pathToIdx = new HashMap<>(); + channelSelectorToInputResourcePathParam.put(sel, pathToIdx); + } + pathToIdx.put(resPath, paramIdx); + } + } + for (ResourcePath resPath: channel.getOutputResources()) { + int paramIdx = resPath.getPathParams().indexOf(sel.getExpression()); + if (paramIdx >= 0) { + Map pathToIdx = channelSelectorToOutputResourcePathParam.get(sel); + if (pathToIdx == null) { + pathToIdx = new HashMap<>(); + channelSelectorToOutputResourcePathParam.put(sel, pathToIdx); + } + pathToIdx.put(resPath, paramIdx); + } + } + } + } + + public DataTransferChannel getChannel() { + return channel; + } + + public Expression getMessage() { + return message; + } + + public void setMessage(Expression message) { + this.message = message; + } + + public boolean isInput() { + return isInput; + } + + public List> getChannelSelectorAndValues() { + return channelSelectorAndValues; + } + + public List getChannelSelectorValues() { + List channelValues = new ArrayList<>(); + for (Map.Entry chEnt: channelSelectorAndValues) { + channelValues.add(chEnt.getValue()); + } + return channelValues; + } + + public void updateChannelSelectorValues(List channelSelectorValues) { + for (int i = 0; i < channelSelectorValues.size(); i++) { + Map.Entry chEnt = channelSelectorAndValues.get(i); + chEnt.setValue(channelSelectorValues.get(i)); + } + } + + public Map getDependingParameters() { + return dependingParameters; + } + + + public Term updateDependingParameters(IResourceStateValueProvider resourceStateValueProvider) { + IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = getInputResourceIdentifier(target.getResource()); + return resourceStateValueProvider.getCurrentStateValueOf(resId); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = getInputResourceIdentifier(target.getResource()); + return resourceStateValueProvider.getNextStateValueOf(resId); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { + ResourceIdentifier resId = getInputResourceIdentifier(target); + return resourceStateValueProvider.getCurrentStateValueOf(resId); + } + }; + + try { + Map> substitutedPositionsInMessageFromChannels = new HashMap<>(); + Term unifiedMessage = null; + + // Calculate message constraints from leaf channel members on the channel member dependency graph. + Map> dependency = channel.getMemberDependency(); + Set toResolve = new HashSet<>(); + Set resolved = new HashSet<>(); + for (Set depended: dependency.values()) { + toResolve.addAll(depended); + } + for (ChannelMember depending: dependency.keySet()) { + toResolve.remove(depending); + } + for (ChannelMember leafMember: toResolve) { + Expression messageConstraint = null; + if (channel.getInputChannelMembers().contains(leafMember)) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } else if (channel.getReferenceChannelMembers().contains(leafMember)) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(leafMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + resolved.addAll(toResolve); + toResolve.clear(); + + for (;;) { + for (Map.Entry> dependEnt: dependency.entrySet()) { + ChannelMember dependingMem = dependEnt.getKey(); + Set dependedMems = dependEnt.getValue(); + if (!resolved.contains(dependingMem) && resolved.containsAll(dependedMems)) { + toResolve.add(dependingMem); + } + } + if (toResolve.size() == 0) break; + for (ChannelMember dependingMem: toResolve) { + // Fill the path parameters of the resource path of a depending channel member. + Set dependingVarPosInMessage = new HashSet<>(); + ResourcePath filledResPath = channel.fillOutsideResourcePath(dependingMem.getResource(), unifiedMessage, dependingMem.getStateTransition().getMessageExpression(), dependingVarPosInMessage); + ResourcePath unfilledResPath = dependingMem.getResource(); + for (int i = 0; i < unfilledResPath.getPathParams().size(); i++) { + Expression var = unfilledResPath.getPathParams().get(i); + Expression val = filledResPath.getPathParams().get(i); + boolean isSelector = false; + for (Selector sel: channel.getAllSelectors()) { + if (sel.getExpression().equals(var)) { + isSelector = true; + break; + } + } + if (!isSelector) { + // A depending channel parameter + updateDependingParameter(var, val); + } + } + + // Calculate message constraint + Expression messageConstraint = null; + if (channel.getInputChannelMembers().contains(dependingMem)) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } else if (channel.getReferenceChannelMembers().contains(dependingMem)) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(dependingMem, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + } + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + resolved.addAll(toResolve); + toResolve.clear(); + } + return unifiedMessage; + } catch (ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed e) { + e.printStackTrace(); + } + return null; + } + + public void updateDependingParameter(Expression variable, Expression value) { + dependingParameters.put(variable, value); + } + + public ResourcePath getInputResourcePath() { + return inputResourcePath; + } + + public Set getInputResources() { + return inputResources; + } + + public Set getOutputResources() { + return outputResources; + } + + public Set getSuccessors() { + return succEvents; + } + + public void addSuccessor(Event succEvt) { + succEvents.add(succEvt); + } + + public ResourceIdentifier getResourceIdentifier(ResourcePath resPath) { + ResourceIdentifier resId = ResourceIdentifier.createFrom(resPath); + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + Map inputPathParamEnt = channelSelectorToInputResourcePathParam.get(sel); + if (inputPathParamEnt != null) { + Integer paramIdx = inputPathParamEnt.get(resPath); + if (paramIdx != null) { + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } + } + } + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + Map outputPathParamEnt = channelSelectorToOutputResourcePathParam.get(sel); + if (outputPathParamEnt != null) { + Integer paramIdx = outputPathParamEnt.get(resPath); + if (paramIdx != null) { + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } + } + } + for (Expression var: dependingParameters.keySet()) { + int paramIdx = resId.getPathParams().indexOf(var); + if (paramIdx >= 0) { + resId.setPathParam(paramIdx, (Constant) dependingParameters.get(var)); + } + } + return resId; + } + + public ResourceIdentifier getInputResourceIdentifier(ResourcePath inputResPath) { + ResourceIdentifier resId = ResourceIdentifier.createFrom(inputResPath); + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + Integer paramIdx = channelSelectorToInputResourcePathParam.get(sel).get(inputResPath); + if (paramIdx != null) { + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } + } + for (Expression var: dependingParameters.keySet()) { + int paramIdx = resId.getPathParams().indexOf(var); + if (paramIdx >= 0) { + resId.setPathParam(paramIdx, (Constant) dependingParameters.get(var)); + } + } + return resId; + } + + public ResourceIdentifier getOutputResourceIdentifier(ResourcePath outputResPath) { + ResourceIdentifier resId = ResourceIdentifier.createFrom(outputResPath); + for (Map.Entry chParamEnt: channelSelectorAndValues) { + Selector sel = chParamEnt.getKey(); + Integer paramIdx = channelSelectorToOutputResourcePathParam.get(sel).get(outputResPath); + if (paramIdx != null) { + resId.setPathParam(paramIdx, chParamEnt.getValue()); + } + } + for (Expression var: dependingParameters.keySet()) { + int paramIdx = resId.getPathParams().indexOf(var); + if (paramIdx >= 0) { + resId.setPathParam(paramIdx, (Constant) dependingParameters.get(var)); + } + } + return resId; + } + + + public interface IResourceStateValueProvider { + Expression getCurrentStateValueOf(ResourceIdentifier resId); + Expression getNextStateValueOf(ResourceIdentifier resId); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java new file mode 100644 index 0000000..665d4a9 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -0,0 +1,161 @@ +package simulator; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import models.algebra.Constant; +import models.algebra.Type; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataConstraintModel.ResourcePath; +import simulator.states.*; + +public class Resource { + private Resource parent = null; + private List children = null; + private ResourceHierarchy resourceHierarchy = null; + private ResourceState state = null; + private Constant parameter = null; + + public Resource(ResourceHierarchy resourceHierarchy) { + this.resourceHierarchy = resourceHierarchy; + if (resourceHierarchy.getChildren().size() > 0) { + ResourceHierarchy childRes = resourceHierarchy.getChildren().iterator().next(); + if (childRes.getNumParameters() > 0) { + Type resType = resourceHierarchy.getResourceStateType(); + if (DataConstraintModel.typeList.isAncestorOf(resType)) { + // List resource + state = new ListResourceState(); + } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { + // Map resource + state = new MapResourceState(); + } + } else { + // Json resource + state = new JsonResourceState(); + children = new ArrayList<>(); + for (ResourceHierarchy child: resourceHierarchy.getChildren()) { + Resource cRes = new Resource(child); + ((JsonResourceState) state).addChildState(child.getResourceName(), cRes.getState()); + children.add(cRes); + } + } + } else { + state = new PrimitiveResourceState((Constant) resourceHierarchy.getInitialValue()); + } + } + + public Resource(ResourceHierarchy resourceHierarchy, Resource parent, ResourceState state) { + this.resourceHierarchy = resourceHierarchy; + this.parent = parent; + this.state = state; + } + + public Resource(ResourceHierarchy resourceHierarchy, Resource parent, Constant parameter, ResourceState state) { + this.resourceHierarchy = resourceHierarchy; + this.parent = parent; + this.parameter = parameter; + this.state = state; + } + + public Resource getParent() { + return parent; + } + + public void setParent(Resource parent) { + this.parent = parent; + } + + public ResourceHierarchy getResourceHierarchy() { + return resourceHierarchy; + } + + public ResourceIdentifier getResourceIdentifier() { + ResourceIdentifier resId = null; + if (parent != null) { + ResourceIdentifier parentResId = parent.getResourceIdentifier(); + if (resourceHierarchy.getNumParameters() == 0) { + resId = new ResourceIdentifier(parentResId, resourceHierarchy.getResourceName(), resourceHierarchy); + } else { + resId = new ResourceIdentifier(parentResId, parameter, resourceHierarchy); + } + } else { + resId = new ResourceIdentifier(resourceHierarchy.getResourceName(), resourceHierarchy); + } + return resId; + } + + public ResourceState getState() { + return state; + } + + public void changeState(ResourceState state) { + this.state = state; + } + + public Constant getParameter() { + return parameter; + } + + public List getChildren() { + List children = null; + if (resourceHierarchy.getChildren().size() > 0) { + children = new ArrayList<>(); + ResourceHierarchy childRes = resourceHierarchy.getChildren().iterator().next(); + if (childRes.getNumParameters() > 0) { + // List or Map type. + if (state instanceof CompositeResourceState) { + // If the list or map is not nil. + Map childStates = ((CompositeResourceState) state).getChildStates(); + for (Map.Entry childEnt: childStates.entrySet()) { + String childParam = childEnt.getKey(); + ResourceState childState = childEnt.getValue(); + Type thisType = resourceHierarchy.getResourceStateType(); + if (DataConstraintModel.typeList.isAncestorOf(thisType)) { + children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeInt), childState)); + } else if (DataConstraintModel.typeMap.isAncestorOf(thisType)) { + children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); + } + } + } + } else { + // Json type. + if (this.children == null) { + Map childStates = ((CompositeResourceState) state).getChildStates(); + for (Map.Entry childEnt: childStates.entrySet()) { + String childParam = childEnt.getKey(); + ResourceState childState = childEnt.getValue(); + Type thisType = resourceHierarchy.getResourceStateType(); + if (DataConstraintModel.typeJson.isAncestorOf(thisType)) { + children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); + } + } + this.children = children; + } + return this.children; + } + } + return children; + } + + public Resource getDescendant(ResourceIdentifier resId) { + if (this.getResourceIdentifier().equals(resId)) return this; + if (!resId.startsWith(this.getResourceIdentifier())) return null; + for (Resource child: getChildren()) { + Resource res = child.getDescendant(resId); + if (res != null) return res; + } + return null; + } + + public Resource getDescendant(String resId) { + if (this.getResourceIdentifier().toString().equals(resId)) return this; + if (!resId.startsWith(this.getResourceIdentifier().toString())) return null; + for (Resource child: getChildren()) { + Resource res = child.getDescendant(resId); + if (res != null) return res; + } + return null; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java b/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java new file mode 100644 index 0000000..d454391 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ResourceIdentifier.java @@ -0,0 +1,126 @@ +package simulator; + +import java.util.HashMap; +import java.util.Map; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; + +public class ResourceIdentifier extends ResourcePath { + + public ResourceIdentifier(String fullResourceName, ResourceHierarchy resourceHierarchy) { + super(fullResourceName, resourceHierarchy); + } + + public ResourceIdentifier(ResourceIdentifier parentResId, String leafResourceName, ResourceHierarchy resourceHierarchy) { + super(parentResId, leafResourceName, resourceHierarchy); + } + + public ResourceIdentifier(ResourceIdentifier parentResId, Expression exp, ResourceHierarchy resourceHierarchy) { + super(parentResId, exp, resourceHierarchy); + } + + public void setPathParam(int paramIdx, Constant param) { + pathParams.set(paramIdx, param); + } + + public boolean equals(ResourceIdentifier another) { + if (!this.getResourceHierarchy().toString().equals(another.getResourceHierarchy().toString())) return false; + ResourceIdentifier resId = this; + while (resId != null && another != null) { + if (resId.getResourceHierarchy().getNumParameters() == 0) { + if (!another.getResourceHierarchy().getResourceName().equals(resId.getResourceHierarchy().getResourceName())) { + return false; + } + } else { + if (!another.getLastParam().equals(resId.getLastParam())) { + return false; + } + } + resId = (ResourceIdentifier) resId.getParent(); + another = (ResourceIdentifier) another.getParent(); + } + return true; + } + + public boolean startsWith(ResourceIdentifier another) { + if (this.length() > another.length()) { + return ((ResourceIdentifier) parent).startsWith(another); + } + return this.equals(another); + } + + public int length() { + if (parent == null) { + return 1; + } + return ((ResourceIdentifier) parent).length() + 1; + } + + public String toString() { + String resId = ""; + if (parent != null) { + resId += parent.toString() + "."; + } + if (!this.endsWithParam()) { + resId += getLeafResourceName(); + } else { + resId += getLastParam().toString().replace("\"", ""); + } + return resId; + } + + public boolean isInstanceOf(ResourcePath resPath) { + ResourcePath resId = this; + while (resId != null && resPath != null) { + if (resId.getResourceHierarchy().getNumParameters() == 0) { + if (!resPath.getResourceHierarchy().getResourceName().equals(resId.getResourceHierarchy().getResourceName())) { + return false; + } + } else if (resId.getResourceHierarchy().getNumParameters() != resPath.getResourceHierarchy().getNumParameters()) { + return false; + } + resId = resId.getParent(); + resPath = resPath.getParent(); + } + return true; + } + + public Map extractParameters(ResourcePath resPath) { + ResourcePath resId = this; + Map paramMap = new HashMap<>(); + while (resId != null && resPath != null) { + if (resId.getResourceHierarchy().getNumParameters() > 0) { + paramMap.put(resPath.getLastParam(), (Constant) resId.getLastParam()); + } else { + if (!resPath.getName().equals(resId.getName())) { + return null; + } + } + resId = resId.getParent(); + resPath = resPath.getParent(); + } + return paramMap; + } + + public static ResourceIdentifier createFrom(ResourcePath resPath) { + ResourceIdentifier parent = null; + if (resPath.getParent() != null) { + parent = createFrom(resPath.getParent()); + } + ResourceHierarchy res = resPath.getResourceHierarchy(); + if (res.getNumParameters() == 0) { + if (parent == null) { + return new ResourceIdentifier(resPath.getLeafResourceName(), res); + } else { + return new ResourceIdentifier(parent, resPath.getLeafResourceName(), res); + } + } else { + return new ResourceIdentifier(parent, resPath.getLastParam(), res); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java new file mode 100644 index 0000000..7d902c5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -0,0 +1,246 @@ +package simulator; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; +import simulator.Event.IResourceStateValueProvider; + +public class Simulator { + private DataTransferModel model; + private SystemState curState; + + public Simulator(DataTransferModel model) { + this.model = model; + init(); + } + + public DataTransferModel getModel() { + return model; + } + + public SystemState init() { + curState = new SystemState(); + for (ResourceHierarchy res: model.getResourceHierarchies()) { + if (res.getParent() == null) { + // root resource + curState.addResource(new Resource(res)); + } + } + for (Channel channel: model.getChannels()) { + curState.addChannel((DataTransferChannel) channel); + } + return curState; + } + + public SystemState getCurState() { + return curState; + } + + /** + * Change the state of the system for a given input event. + * + * @param inputEvent an input event + * @return the next system state + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public SystemState transition(Event inputEvent) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + SystemState nextSystemState = new SystemState(curState); + nextSystemState.addEvent(inputEvent); + + fireEvent(inputEvent, curState, nextSystemState); + + curState = nextSystemState; + return nextSystemState; + } + + /** + * Fire an given event and construct the next system state from the current system state. + * + * @param event an event + * @param curSystemState the current state of the system + * @param nextSystemState the next state of the system to be constructed + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + private void fireEvent(final Event event, final SystemState curSystemState, final SystemState nextSystemState) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + IResourceStateAccessor resouceStateAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = event.getResourceIdentifier(target.getResource()); + Resource res = curSystemState.getResource(resId); + if (res == null) return null; + return res.getState().getValue(); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourceIdentifier resId = event.getResourceIdentifier(target.getResource()); + Resource res = nextSystemState.getResource(resId); + if (res == null) return null; + return res.getState().getValue(); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath target, ResourcePath from) { + ResourceIdentifier resId = event.getResourceIdentifier(target); + Resource res = curSystemState.getResource(resId); + if (res == null) return null; + return res.getState().getValue(); + } + }; + + DataTransferChannel channel = event.getChannel(); + if (channel.getOutputResources().size() > 0) { + // For each output resource, calculate the next state. + for (ChannelMember out: channel.getOutputChannelMembers()) { + Expression nextResState = null; + if (!event.isInput()) { + nextResState = channel.deriveUpdateExpressionOf(out, resouceStateAccessor).getKey(); + } else { + nextResState = channel.deriveUpdateExpressionOf(out, (Term) event.getMessage(), resouceStateAccessor); + } + ResourceIdentifier outResId = event.getOutputResourceIdentifier(out.getResource()); + if (nextResState instanceof Term) { + nextResState = ((Term) nextResState).reduce(); + } + ResourceIdentifier updatedOutResId = nextSystemState.updateResourceState(outResId, nextResState); + while (updatedOutResId != null) { // In addition to the target state, its descendants' states are also changed. + for (Event nextEvent: getNextEvents(updatedOutResId, curSystemState, nextSystemState)) { + fireEvent(nextEvent, curSystemState, nextSystemState); + } + updatedOutResId = (ResourceIdentifier) updatedOutResId.getParent(); + } + } + } + } + + private Set getNextEvents(ResourceIdentifier inResId, final SystemState curSystemState, final SystemState nextSystemState) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + Set nextEvents = new HashSet<>(); + IResourceStateValueProvider resourceStateValueProvider = new IResourceStateValueProvider() { + @Override + public Expression getCurrentStateValueOf(ResourceIdentifier resId) { + return curSystemState.getResource(resId).getState().getValue(); + } + + @Override + public Expression getNextStateValueOf(ResourceIdentifier resId) { + return nextSystemState.getResource(resId).getState().getValue(); + } + }; + for (Map.Entry chEntry: nextSystemState.getChannelStates().entrySet()) { + DataTransferChannel channel = chEntry.getKey(); + ChannelState nextChState = chEntry.getValue(); + Map> dependency = channel.getMemberDependency(); + Map> invDependency = new HashMap<>(); + for (ChannelMember dependingMem: dependency.keySet()) { + for (ChannelMember dependedMem: dependency.get(dependingMem)) { + Set dependings = invDependency.get(dependedMem); + if (dependings == null) { + dependings = new HashSet<>(); + invDependency.put(dependedMem, dependings); + } + dependings.add(dependingMem); + } + } + for (ResourcePath inResPath: channel.getInputResources()) { + if (inResId.isInstanceOf(inResPath)) { + // Update the channel state and resource identifiers by the update of the input resource. + for (ChannelMember dependedMem: invDependency.keySet()) { + if (inResPath == dependedMem.getResource()) { + // If some depending resources are to be updated by the update of an depended input resource. + final Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); + nextEvent.updateDependingParameters(resourceStateValueProvider); + if (nextChState == null) { + nextChState = new ChannelState(channel); + nextSystemState.updateChannelState(channel, nextChState); + } + List channelSelValues = nextEvent.getChannelSelectorValues(); + for (Map.Entry paramEnt: nextEvent.getDependingParameters().entrySet()) { + nextChState.addDependingParamAndValue(channelSelValues, paramEnt.getKey(), paramEnt.getValue()); + } + nextEvents.add(nextEvent); + } + } + if (nextChState != null) { + for (ChannelMember dependingMem: dependency.keySet()) { + if (inResPath == dependingMem.getResource()) { + // If a depending resource is directly updated. + ResourcePath filledResPath = inResId; + ResourcePath unfilledResPath = inResPath; + Map selectorVarToVal = new HashMap<>(); + Map dependingVarToVal = new HashMap<>(); + for (int i = 0; i < unfilledResPath.getPathParams().size(); i++) { + Expression var = unfilledResPath.getPathParams().get(i); + Expression val = filledResPath.getPathParams().get(i); + boolean isSelector = false; + for (Selector sel: channel.getAllSelectors()) { + if (sel.getExpression().equals(var)) { + isSelector = true; + break; + } + } + if (isSelector) { + selectorVarToVal.put(var, val); + } else { + dependingVarToVal.put(var, val); + } + } + for (List channelSelectorValues: nextChState.getDependedChannelSelectorValues(dependingVarToVal)) { + // Guess every tuple of channel selector values that may affects the updated resource. + boolean doesMatch = true; + for (Expression var: selectorVarToVal.keySet()) { + for (int i = 0; i < channel.getAllSelectors().size(); i++) { + if (channel.getAllSelectors().get(i).getExpression().equals(var)) { + if (!channelSelectorValues.get(i).equals(selectorVarToVal.get(var))) { + // If the value of a selector in the updated resource path does not matches a guessed channel selector value. + doesMatch = false; + } + } + } + } + if (doesMatch) { + Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId), channelSelectorValues, dependingVarToVal); + nextEvents.add(nextEvent); + } + } + } + } + } + } + } + } + return nextEvents; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java new file mode 100644 index 0000000..494ac79 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -0,0 +1,273 @@ +package simulator; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.algebra.Type; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataFlowModel.DataTransferChannel; +import simulator.states.CompositeResourceState; +import simulator.states.JsonResourceState; +import simulator.states.ListResourceState; +import simulator.states.MapResourceState; +import simulator.states.PrimitiveResourceState; +import simulator.states.ResourceState; + +public class SystemState { + private Set rootResources = new HashSet<>(); + private Map channelStates = new HashMap<>(); + private List events = new ArrayList<>(); + + public SystemState() { + } + + public SystemState(SystemState prevState) { + rootResources = new HashSet<>(prevState.getRootResources()); + channelStates = new HashMap<>(prevState.getChannelStates()); + } + + public Set getRootResources() { + return rootResources; + } + + public void addResource(Resource rootResource) { + rootResources.add(rootResource); + } + + public Resource getResource(ResourceIdentifier resourceIdentifier) { + for (Resource root: rootResources) { + Resource descendant = root.getDescendant(resourceIdentifier); + if (descendant != null) return descendant; + } + return null; + } + + public Resource getResource(String resourceIdentifier) { + for (Resource root: rootResources) { + Resource descendant = root.getDescendant(resourceIdentifier); + if (descendant != null) return descendant; + } + return null; + } + + public ResourceIdentifier updateResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { + Type resType = resourceIdentifier.getResourceStateType(); + if (resType != null && DataConstraintModel.typeList.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term listValue = (Term) resStateValue; + if (listValue.getSymbol().equals(DataConstraintModel.append)) { + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + Expression childExp = null; + if (state instanceof ListResourceState) { + childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + } else if (state instanceof PrimitiveResourceState && ((PrimitiveResourceState) state).getValue().getSymbol().equals(DataConstraintModel.nil)) { + // If the value of state is nil. + childExp = new Constant("0"); + ResourceState parentState = res.getParent().getState(); + ResourceState newState = new ListResourceState(); + if (parentState instanceof CompositeResourceState) { + ((CompositeResourceState) parentState).replaceChildState(state, newState); + } + state = newState; + res.changeState(state); + } + ResourceHierarchy childResourceHierarchy = null; + if (resourceIdentifier.getResourceHierarchy().getChildren() != null && resourceIdentifier.getResourceHierarchy().getChildren().size() > 0) { + childResourceHierarchy = resourceIdentifier.getResourceHierarchy().getChildren().iterator().next(); + } else { + childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1); + } + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.getChild(1)); + ((ListResourceState) state).addChildState(childInfo.getKey()); + return childInfo.getValue(); + } + } + } else if (resType != null && DataConstraintModel.typeMap.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term mapValue = (Term) resStateValue; + if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { + Expression childExp = mapValue.getChild(1); + if (childExp instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + if (state instanceof PrimitiveResourceState && ((PrimitiveResourceState) state).getValue().getSymbol().equals(DataConstraintModel.nil)) { + // If the value of state is nil. + ResourceState parentState = res.getParent().getState(); + ResourceState newState = new MapResourceState(); + if (parentState instanceof CompositeResourceState) { + ((CompositeResourceState) parentState).replaceChildState(state, newState); + } + state = newState; + res.changeState(state); + } + ResourceHierarchy childResourceHierarchy = null; + if (resourceIdentifier.getResourceHierarchy().getChildren() != null && resourceIdentifier.getResourceHierarchy().getChildren().size() > 0) { + childResourceHierarchy = resourceIdentifier.getResourceHierarchy().getChildren().iterator().next(); + } else { + childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), 1); + } + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, childResourceHierarchy); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.getChild(2)); + ((MapResourceState) state).addChildState(childId, childInfo.getKey()); + return childInfo.getValue(); + } + } + } + } else if (resType != null && DataConstraintModel.typeJson.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term jsonValue = (Term) resStateValue; + if (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { + Expression childExp = jsonValue.getChild(1); + if (childExp instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); + ((JsonResourceState) state).addChildState(childId, childInfo.getKey()); + return childInfo.getValue(); + } + } + } + } else { + if (resStateValue instanceof Term) { + resStateValue = ((Term) resStateValue).reduce(); + } + if (resStateValue instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = null; + if (res != null) { + state = res.getState(); + ((PrimitiveResourceState) state).setValue((Constant) resStateValue); + } else { + ResourceIdentifier parentResId = (ResourceIdentifier) resourceIdentifier.getParent(); + Type parentResType = parentResId.getResourceStateType(); + if (parentResType != null && DataConstraintModel.typeList.isAncestorOf(parentResType)) { + } else if (parentResType != null && DataConstraintModel.typeMap.isAncestorOf(parentResType)) { + JsonResourceState parentState = (JsonResourceState) getResource(parentResId).getState(); + parentState.addChildState(((Constant) resourceIdentifier.getLastParam()).toString(), new PrimitiveResourceState((Constant) resStateValue)); + } else if (parentResType != null && DataConstraintModel.typeJson.isAncestorOf(parentResType)) { + JsonResourceState parentState = (JsonResourceState) getResource(parentResId).getState(); + parentState.addChildState("\"" + resourceIdentifier.getLeafResourceName() + "\"", new PrimitiveResourceState((Constant) resStateValue)); + } + } + return resourceIdentifier; + } + } + return resourceIdentifier; + } + + public Map.Entry createResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { + Type resType = null; + if (resStateValue instanceof Term) { + resType = ((Term) resStateValue).getType(); + } + if (resType != null) { + if (DataConstraintModel.typeList.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term listValue = (Term) resStateValue; + if (listValue.getSymbol().equals(DataConstraintModel.append)) { + ListResourceState state = new ListResourceState(); + Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.getChild(1)); + state.addChildState(childInfo.getKey()); + return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + } + } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term mapValue = (Term) resStateValue; + if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { + Expression childExp = mapValue.getChild(1); + if (childExp instanceof Constant) { + MapResourceState state = new MapResourceState(); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.getChild(2)); + state.addChildState(childId, childInfo.getKey()); + return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + } + } + } else if (DataConstraintModel.typeJson.isAncestorOf(resType)) { + if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof Term) { + Term jsonValue = (Term) resStateValue; + if (jsonValue.getSymbol().equals(DataConstraintModel.addMember)) { + Expression childExp = jsonValue.getChild(1); + if (childExp instanceof Constant) { + JsonResourceState state = new JsonResourceState(); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + ((Constant) childExp).getSymbol().getName(), + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + String childId = ((Constant) childExp).toString(); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.getChild(2)); + state.addChildState(childId, childInfo.getKey()); + return new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + } + } + } + } + if (resStateValue instanceof Constant) { + Resource res = getResource(resourceIdentifier); + ResourceState state = null; + if (res != null) { + state = res.getState(); + ((PrimitiveResourceState) state).setValue((Constant) resStateValue); + } else { + state = new PrimitiveResourceState((Constant) resStateValue); + } + return new AbstractMap.SimpleEntry<>(state, resourceIdentifier); + } + return null; + } + + public Map getChannelStates() { + return channelStates; + } + + public ChannelState getChannelState(DataTransferChannel channel) { + return channelStates.get(channel); + } + + public void addChannel(DataTransferChannel channel) { + channelStates.put(channel, null); + } + + public void updateChannelState(DataTransferChannel channel, ChannelState channelState) { + channelStates.put(channel, channelState); + } + + public List getEvents() { + return events; + } + + public void addEvent(Event event) { + events.add(event); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/CompositeResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/CompositeResourceState.java new file mode 100644 index 0000000..5e6311f --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/CompositeResourceState.java @@ -0,0 +1,14 @@ +package simulator.states; + +import java.util.Map; + +public abstract class CompositeResourceState extends ResourceState { + @Override + boolean hasChildren() { + return true; + } + + public abstract Map getChildStates(); + + public abstract void replaceChildState(ResourceState state, ResourceState newState); +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java new file mode 100644 index 0000000..afd1c20 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java @@ -0,0 +1,45 @@ +package simulator.states; + +import java.util.HashMap; +import java.util.Map; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.DataConstraintModel; + +public class JsonResourceState extends CompositeResourceState { + private Map children = new HashMap<>(); + + @Override + public Expression getValue() { + Term value = new Constant(DataConstraintModel.nil); + value.setType(DataConstraintModel.typeJson); + for (Map.Entry childEnt: children.entrySet()) { + Term newTerm = new Term(DataConstraintModel.addMember); + newTerm.addChild(value); + newTerm.addChild(new Constant(childEnt.getKey(), DataConstraintModel.typeString)); + newTerm.addChild(childEnt.getValue().getValue()); + value = newTerm; + } + return value; + } + + @Override + public Map getChildStates() { + return children; + } + + public void addChildState(String param, ResourceState childState) { + children.put(param, childState); + } + + @Override + public void replaceChildState(ResourceState state, ResourceState newState) { + for (Map.Entry childEnt: children.entrySet()) { + if (childEnt.getValue().equals(state)) { + children.put(childEnt.getKey(), newState); + } + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java new file mode 100644 index 0000000..83367e0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java @@ -0,0 +1,51 @@ +package simulator.states; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.DataConstraintModel; + +public class ListResourceState extends CompositeResourceState { + private List children = new ArrayList<>(); + + @Override + public Expression getValue() { + Term value = new Constant(DataConstraintModel.nil); + value.setType(DataConstraintModel.typeList); + for (ResourceState child: children) { + Term newTerm = new Term(DataConstraintModel.append); + newTerm.addChild(value); + newTerm.addChild(child.getValue()); + value = newTerm; + } + return value; + } + + @Override + public Map getChildStates() { + Map childParams = new HashMap<>(); + for (int i = 0; i < children.size(); i++) { + childParams.put(Integer.toString(i), children.get(i)); + } + return childParams; + } + + public void addChildState(ResourceState childState) { + children.add(childState); + } + + + @Override + public void replaceChildState(ResourceState state, ResourceState newState) { + for (int i = 0; i < children.size(); i++) { + if (children.get(i).equals(state)) { + children.set(i, newState); + } + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java new file mode 100644 index 0000000..5bd2fc7 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java @@ -0,0 +1,45 @@ +package simulator.states; + +import java.util.HashMap; +import java.util.Map; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.DataConstraintModel; + +public class MapResourceState extends CompositeResourceState { + private Map children = new HashMap<>(); + + @Override + public Expression getValue() { + Term value = new Constant(DataConstraintModel.nil); + value.setType(DataConstraintModel.typeMap); + for (Map.Entry childEnt: children.entrySet()) { + Term newTerm = new Term(DataConstraintModel.insert); + newTerm.addChild(value); + newTerm.addChild(new Constant(childEnt.getKey(), DataConstraintModel.typeString)); + newTerm.addChild(childEnt.getValue().getValue()); + value = newTerm; + } + return value; + } + + @Override + public Map getChildStates() { + return children; + } + + public void addChildState(String param, ResourceState childState) { + children.put(param, childState); + } + + @Override + public void replaceChildState(ResourceState state, ResourceState newState) { + for (Map.Entry childEnt: children.entrySet()) { + if (childEnt.getValue().equals(state)) { + children.put(childEnt.getKey(), newState); + } + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java new file mode 100644 index 0000000..6ad1362 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java @@ -0,0 +1,25 @@ +package simulator.states; + +import models.algebra.Constant; + +public class PrimitiveResourceState extends ResourceState { + private Constant value; + + public PrimitiveResourceState(Constant initialValue) { + value = initialValue; + } + + @Override + public Constant getValue() { + return value; + } + + public void setValue(Constant newValue) { + value = newValue; + } + + @Override + boolean hasChildren() { + return false; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/ResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/ResourceState.java new file mode 100644 index 0000000..7eba6c7 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/ResourceState.java @@ -0,0 +1,5 @@ +package simulator.states; + +abstract public class ResourceState extends State { + abstract boolean hasChildren(); +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java new file mode 100644 index 0000000..f9286dd --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java @@ -0,0 +1,7 @@ +package simulator.states; + +import models.algebra.Expression; + +abstract public class State { + abstract public Expression getValue(); +} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java deleted file mode 100644 index ffbef05..0000000 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package tests; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import models.*; -import models.algebra.Variable; -import models.dataConstraintModel.*; -import models.dataFlowModel.*; - -public class DataFlowModelTest { - - @Test - public void test() { - // Construct a data-flow architecture model. - DataTransferModel model = new DataTransferModel(); - - ResourcePath customers = new ResourcePath("customers"); // "customers" - ResourcePath customer = new ResourcePath(customers, new Variable("uid")); // "customers.{uid}" - ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" - ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" - ResourcePath companies = new ResourcePath("companies"); // "companies" - ResourcePath company = new ResourcePath(companies, new Variable("cid")); // "companies.{cid}" - ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" - model.addResourcePath(customer_off); - model.addResourcePath(customer_add); - model.addResourcePath(company_add); - - // === cio_setCustomerOff(uid) === - // - // out customers.{uid}.off(c, set(x)) == x - // - DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office (an input channel) - ChannelMember customer_off_1 = new ChannelMember(customer_off); - cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1); - assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getSelectors().iterator().next().getExpression()); - - // === cio_setCompanyAdd(cid) === - // - // out companies.{cid}.add(a, set(y)) == y - // - DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address (an input channel) - ChannelMember company_add_1 = new ChannelMember(company_add); - cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1); - assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getSelectors().iterator().next().getExpression()); - - // === c === - // - // in customers.{uid}.off( c, update(cid, a2)) == cid - // in companies.{cid}.add( a, update(cid, a2)) == a2 - // out customers.{uid}.add(b, update(cid, a2)) == a2 - // - DataTransferChannel c = new DataTransferChannel("c", new Variable("uid")); // update customer's address - ChannelMember customer_off_2 = new ChannelMember(customer_off); - ChannelMember company_add_2 = new ChannelMember(company_add); - ChannelMember customer_add_2 = new ChannelMember(customer_add); - c.addChannelMemberAsInput(customer_off_2); - c.addChannelMemberAsInput(company_add_2); - c.addChannelMemberAsOutput(customer_add_2); - assertEquals(customer_off.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); - assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); - assertEquals(company_add.getPathParams().get(0), new Variable("cid")); - - // Construct a data-flow architecture model. - model.addIOChannel(cio_setCustomerOff); - model.addIOChannel(cio_setCompanyAdd); - model.addChannel(c); - - // Check the model. - assertEquals(3, model.getResourcePaths().size()); - assertEquals(7, model.getResourceHierarchies().size()); - assertEquals(2, model.getIOChannels().size()); - assertEquals(1, model.getChannels().size()); - - // Extract the resource dependency graph. - DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); - - // Check the graph. - assertEquals(7, resourceDependencyGraph.getResourceNodes().size()); - assertEquals(3, resourceDependencyGraph.getChannelNodes().size()); - assertEquals(5, resourceDependencyGraph.getEdges().size()); - for (Edge e: resourceDependencyGraph.getEdges()) { - System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); - } - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java new file mode 100644 index 0000000..5f1b3c3 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java @@ -0,0 +1,88 @@ +package tests; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import models.*; +import models.algebra.Variable; +import models.dataConstraintModel.*; +import models.dataFlowModel.*; + +public class DataTransferModelTest { + + @Test + public void test() { + // Construct a data-flow architecture model. + DataTransferModel model = new DataTransferModel(); + + ResourcePath customers = new ResourcePath("customers"); // "customers" + ResourcePath customer = new ResourcePath(customers, new Variable("uid")); // "customers.{uid}" + ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" + ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" + ResourcePath companies = new ResourcePath("companies"); // "companies" + ResourcePath company = new ResourcePath(companies, new Variable("cid")); // "companies.{cid}" + ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" + model.addResourcePath(customer_off); + model.addResourcePath(customer_add); + model.addResourcePath(company_add); + + // === cio_setCustomerOff(uid) === + // + // out customers.{uid}.off(c, set(x)) = x + // + DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office (an input channel) + ChannelMember customer_off_1 = new ChannelMember(customer_off); + cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1); + assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getSelectors().iterator().next().getExpression()); + + // === cio_setCompanyAdd(cid) === + // + // out companies.{cid}.add(a, set(y)) = y + // + DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address (an input channel) + ChannelMember company_add_1 = new ChannelMember(company_add); + cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1); + assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getSelectors().iterator().next().getExpression()); + + // === c === + // + // in customers.{uid}.off( c, update(cid, a2)) = cid + // in companies.{cid}.add( a, update(cid, a2)) = a2 + // out customers.{uid}.add(b, update(cid, a2)) = a2 + // + DataTransferChannel c = new DataTransferChannel("c", new Variable("uid")); // update customer's address + ChannelMember customer_off_2 = new ChannelMember(customer_off); + ChannelMember company_add_2 = new ChannelMember(company_add); + ChannelMember customer_add_2 = new ChannelMember(customer_add); + c.addChannelMemberAsInput(customer_off_2); + c.addChannelMemberAsInput(company_add_2); + c.addChannelMemberAsOutput(customer_add_2); + assertEquals(customer_off.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); + assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); + assertEquals(company_add.getPathParams().get(0), new Variable("cid")); + + // Construct a data-flow architecture model. + model.addIOChannel(cio_setCustomerOff); + model.addIOChannel(cio_setCompanyAdd); + model.addChannel(c); + + // Check the model. + assertEquals(3, model.getResourcePaths().size()); + assertEquals(7, model.getResourceHierarchies().size()); + assertEquals(2, model.getIOChannels().size()); + assertEquals(1, model.getChannels().size()); + + // Extract the resource dependency graph. + DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); + + // Check the graph. + assertEquals(7, resourceDependencyGraph.getResourceNodes().size()); + assertEquals(3, resourceDependencyGraph.getChannelNodes().size()); + assertEquals(5, resourceDependencyGraph.getEdges().size()); + for (Edge e: resourceDependencyGraph.getEdges()) { + System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java new file mode 100644 index 0000000..cbac9dc --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java @@ -0,0 +1,224 @@ +package tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.algebra.Constant; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import simulator.Event; +import simulator.Resource; +import simulator.Simulator; +import simulator.SystemState; +import simulator.ResourceIdentifier; +import simulator.states.MapResourceState; + +public class SimulatorTest { + @Test + public void test() { + try { + TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + + // Construct a data transfer architecture model. + DataTransferModel model = new DataTransferModel(); + + ResourcePath customers = new ResourcePath("customers"); // "customers" + ResourcePath customer = new ResourcePath(customers, + new Variable("uid", DataConstraintModel.typeString)); // "customers.{uid}" + ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" + ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" + ResourcePath companies = new ResourcePath("companies"); // "companies" + ResourcePath company = new ResourcePath(companies, + new Variable("cid", DataConstraintModel.typeString)); // "companies.{cid}" + ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" + ResourcePath company2 = new ResourcePath(companies, + new Variable("cid2", DataConstraintModel.typeString)); // "companies.{cid2}" + ResourcePath company2_add = new ResourcePath(company2, "add"); // "companies.{cid2}.add" + ResourcePath companyA = new ResourcePath(companies, + new Constant("\"A\"", DataConstraintModel.typeString)); // "companies.A" + ResourcePath companyA_add = new ResourcePath(companyA, "add"); // "companies.{cid2}.add" + model.addResourcePath(customer_off); + model.addResourcePath(customer_add); + model.addResourcePath(company_add); + model.addResourcePath(company2_add); + model.addResourcePath(customers); + model.addResourcePath(companies); + + // For channel CIO_AddCustomer + DataTransferChannel cio_addCustomer = new DataTransferChannel("CIO_AddCustomer"); // add a customer + ChannelMember customers1 = new ChannelMember(customers); + stream.addLine("db:Map"); + Expression curStateExp0 = parser.parseTerm(stream, model); + customers1.getStateTransition().setCurStateExpression(curStateExp0); + stream.addLine("addCustomer(uid:Str, off:Str)"); + Expression messageExp0 = parser.parseTerm(stream, model); + customers1.getStateTransition().setMessageExpression(messageExp0); + stream.addLine("insert(db, uid, {\"off\": off})"); + Expression nextStateExp0 = parser.parseTerm(stream, model); + customers1.getStateTransition().setNextStateExpression(nextStateExp0); + cio_addCustomer.addChannelMemberAsOutput(customers1); + + // For channel CIO_AddCompany + DataTransferChannel cio_addCompany = new DataTransferChannel("CIO_AddCompany"); // add a company + ChannelMember companies1 = new ChannelMember(companies); + stream.addLine("db:Map"); + Expression curStateExp1 = parser.parseTerm(stream, model); + companies1.getStateTransition().setCurStateExpression(curStateExp1); + stream.addLine("addCampany(cid:Str, add:Str)"); + Expression messageExp1 = parser.parseTerm(stream, model); + companies1.getStateTransition().setMessageExpression(messageExp1); + stream.addLine("insert(db, cid, {\"add\": add})"); + Expression nextStateExp1 = parser.parseTerm(stream, model); + companies1.getStateTransition().setNextStateExpression(nextStateExp1); + cio_addCompany.addChannelMemberAsOutput(companies1); + + // For channel CIO_SetCustomerOff + DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office + ChannelMember customer_off_1 = new ChannelMember(customer_off); + stream.addLine("cid:Str"); + Expression curStateExp2 = parser.parseTerm(stream, model); + customer_off_1.getStateTransition().setCurStateExpression(curStateExp2); + stream.addLine("setOff(cid2:Str)"); + Expression messageExp2 = parser.parseTerm(stream, model); + customer_off_1.getStateTransition().setMessageExpression(messageExp2); + stream.addLine("cid2"); + Expression nextStateExp2 = parser.parseTerm(stream, model); + customer_off_1.getStateTransition().setNextStateExpression(nextStateExp2); + cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1); + + // For channel CIO_SetCompanyAdd + DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address + ChannelMember company_add_1 = new ChannelMember(company_add); + stream.addLine("a1:Str"); + Expression curStateExp3 = parser.parseTerm(stream, model); + company_add_1.getStateTransition().setCurStateExpression(curStateExp3); + stream.addLine("setAdd(a2:Str)"); + Expression messageExp3 = parser.parseTerm(stream, model); + company_add_1.getStateTransition().setMessageExpression(messageExp3); + stream.addLine("a2"); + Expression nextStateExp3 = parser.parseTerm(stream, model); + company_add_1.getStateTransition().setNextStateExpression(nextStateExp3); + cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1); + + // For channel C + DataTransferChannel c = new DataTransferChannel("C", new Variable("uid")); // update customer's address + ChannelMember customer_off_2 = new ChannelMember(customer_off); + stream.addLine("cid:Str"); + Expression curStateExp4 = parser.parseTerm(stream, model); + customer_off_2.getStateTransition().setCurStateExpression(curStateExp4); + stream.addLine("sync(cid2:Str, add2:Str)"); + Expression messageExp4 = parser.parseTerm(stream, model); + customer_off_2.getStateTransition().setMessageExpression(messageExp4); + stream.addLine("cid2"); + Expression nextStateExp4 = parser.parseTerm(stream, model); + customer_off_2.getStateTransition().setNextStateExpression(nextStateExp4); + c.addChannelMemberAsInput(customer_off_2); + + ChannelMember company_add_2 = new ChannelMember(company2_add); + stream.addLine("a1:Str"); + Expression curStateExp5 = parser.parseTerm(stream, model); + company_add_2.getStateTransition().setCurStateExpression(curStateExp5); + stream.addLine("sync(cid2:Str, add2:Str)"); + Expression messageExp5 = parser.parseTerm(stream, model); + company_add_2.getStateTransition().setMessageExpression(messageExp5); + stream.addLine("add2"); + Expression nextStateExp5 = parser.parseTerm(stream, model); + company_add_2.getStateTransition().setNextStateExpression(nextStateExp5); + c.addChannelMemberAsInput(company_add_2); + + ChannelMember customer_add_2 = new ChannelMember(customer_add); + stream.addLine("a3:Str"); + Expression curStateExp6 = parser.parseTerm(stream, model); + customer_add_2.getStateTransition().setCurStateExpression(curStateExp6); + stream.addLine("sync(cid2:Str, add2:Str)"); + Expression messageExp6 = parser.parseTerm(stream, model); + customer_add_2.getStateTransition().setMessageExpression(messageExp6); + stream.addLine("add2"); + Expression nextStateExp6 = parser.parseTerm(stream, model); + customer_add_2.getStateTransition().setNextStateExpression(nextStateExp6); + c.addChannelMemberAsOutput(customer_add_2); + + model.addIOChannel(cio_setCustomerOff); + model.addIOChannel(cio_setCompanyAdd); + model.addChannel(c); + + Simulator simulator = new Simulator(model); + + // Initial state + SystemState initialState = simulator.init(); + + assertEquals(2, initialState.getRootResources().size()); + for (Resource rootRes: initialState.getRootResources()) { + assertTrue(rootRes.getState() instanceof MapResourceState); + assertEquals(0, rootRes.getChildren().size()); + assertEquals(0, ((MapResourceState) rootRes.getState()).getChildStates().size()); + } + System.out.println("companies:" + initialState.getResource(ResourceIdentifier.createFrom(companies)).getState().getValue()); + System.out.println("customers:" + initialState.getResource(ResourceIdentifier.createFrom(customers)).getState().getValue()); + + // Next state (companies.addCompany("A", "Osaka")) + stream.addLine("addCompany(\"A\", \"Osaka\")"); + Expression messageAddComp = parser.parseTerm(stream, model); + Event addCompany = new Event(cio_addCompany, messageAddComp, companies, initialState.getResource(ResourceIdentifier.createFrom(companies))); + simulator.transition(addCompany); + SystemState nextState = simulator.getCurState(); + + assertEquals(2, nextState.getRootResources().size()); + Resource companiesRes = nextState.getResource(ResourceIdentifier.createFrom(companies)); + assertTrue(companiesRes.getState() instanceof MapResourceState); + assertEquals(1, companiesRes.getChildren().size()); + assertEquals(1, ((MapResourceState) companiesRes.getState()).getChildStates().size()); + System.out.println("companies:" + nextState.getResource(ResourceIdentifier.createFrom(companies)).getState().getValue()); + System.out.println("customers:" + nextState.getResource(ResourceIdentifier.createFrom(customers)).getState().getValue()); + + // After the next state (customers.addCustomer("1", "A")) + stream.addLine("addCustomer(\"1\", \"A\")"); + Expression messageAddCust = parser.parseTerm(stream, model); + Event addCustomer = new Event(cio_addCustomer, messageAddCust, customers, nextState.getResource(ResourceIdentifier.createFrom(customers))); + simulator.transition(addCustomer); + SystemState nextNextState = simulator.getCurState(); + + assertEquals(2, nextState.getRootResources().size()); + Resource customersRes = nextNextState.getResource(ResourceIdentifier.createFrom(customers)); + assertTrue(customersRes.getState() instanceof MapResourceState); + assertEquals(1, customersRes.getChildren().size()); + assertEquals(1, ((MapResourceState) customersRes.getState()).getChildStates().size()); + System.out.println("companies:" + nextNextState.getResource(ResourceIdentifier.createFrom(companies)).getState().getValue()); + System.out.println("customers:" + nextNextState.getResource(ResourceIdentifier.createFrom(customers)).getState().getValue()); + + // After the next next state (companies.A.setAdd("Tokyo")) + stream.addLine("setAdd(\"Tokyo\")"); + Expression messageSetAdd = parser.parseTerm(stream, model); + Event setAdd = new Event(cio_setCompanyAdd, messageSetAdd, company_add, nextNextState.getResource(ResourceIdentifier.createFrom(companyA_add))); + simulator.transition(setAdd); + SystemState nextNextNextState = simulator.getCurState(); + Resource customersRes2 = nextNextNextState.getResource(ResourceIdentifier.createFrom(customers)); + assertTrue(customersRes2.getState() instanceof MapResourceState); + assertEquals(1, customersRes2.getChildren().size()); + assertEquals(1, ((MapResourceState) customersRes2.getState()).getChildStates().size()); + System.out.println("companies:" + nextNextNextState.getResource(ResourceIdentifier.createFrom(companies)).getState().getValue()); + System.out.println("customers:" + nextNextNextState.getResource(ResourceIdentifier.createFrom(customers)).getState().getValue()); + + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon | ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java index 92c754d..bc1db89 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java @@ -123,8 +123,8 @@ // === c1 === // - // payment(p1, update1(y)) == y - // points(l, update1(y)) == floor(y * 0.05) + // payment(p1, update1(y)) = y + // points(l, update1(y)) = floor(y * 0.05) // DataTransferChannel c1 = new DataTransferChannel("c1"); ChannelMember c1_payment = new ChannelMember(payment); @@ -165,7 +165,7 @@ System.out.println(c1.deriveUpdateExpressionOf(c1_loyalty).toImplementation(sideEffects)); System.out.println("-- PUSH --"); - Expression loyaltyPushUpdate = c1.deriveUpdateExpressionOf(c1_loyalty, pushAccessor); + Expression loyaltyPushUpdate = c1.deriveUpdateExpressionOf(c1_loyalty, pushAccessor).getKey(); Parameter param = null; for (Parameter p: loyaltyPushUpdate.getSubTerms(Parameter.class).values()) { if (p.equals(pPayment) || p.equals(pPoints) || p.equals(pHistory) || p.equals(pTotal)) { @@ -179,7 +179,7 @@ System.out.println("-- PULL --"); System.out.println(points.getResourceStateType().getImplementationTypeName() + " " + pointsGetter.toImplementation() + "() {"); - System.out.println("\t return " + c1.deriveUpdateExpressionOf(c1_loyalty, pullAccessor).toImplementation(sideEffects) + ";"); + System.out.println("\t return " + c1.deriveUpdateExpressionOf(c1_loyalty, pullAccessor).getKey().toImplementation(sideEffects) + ";"); System.out.println("}"); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { @@ -190,8 +190,8 @@ // === c2 === // - // payment(p1, update2(z)) == z - // history(h, update2(z)) == cons(z, h) + // payment(p1, update2(z)) = z + // history(h, update2(z)) = cons(z, h) // DataTransferChannel c2 = new DataTransferChannel("c2"); ChannelMember c2_payment = new ChannelMember(payment); @@ -228,7 +228,7 @@ System.out.println(c2.deriveUpdateExpressionOf(c2_history).toImplementation(sideEffects)); System.out.println("-- PUSH --"); - Expression historyPushUpdate = c2.deriveUpdateExpressionOf(c2_history, pushAccessor); + Expression historyPushUpdate = c2.deriveUpdateExpressionOf(c2_history, pushAccessor).getKey(); Parameter param = null; for (Parameter p: historyPushUpdate.getSubTerms(Parameter.class).values()) { if (p.equals(pPayment) || p.equals(pPoints) || p.equals(pHistory) || p.equals(pTotal)) { @@ -242,7 +242,7 @@ System.out.println("-- PULL --"); System.out.println(history.getResourceStateType().getImplementationTypeName() + " " + historyGetter.toImplementation() + "() {"); - System.out.println("\t return " + c2.deriveUpdateExpressionOf(c2_history, pullAccessor).toImplementation(sideEffects) + ";"); + System.out.println("\t return " + c2.deriveUpdateExpressionOf(c2_history, pullAccessor).getKey().toImplementation(sideEffects) + ";"); System.out.println("}"); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { @@ -291,7 +291,7 @@ System.out.println(c3.deriveUpdateExpressionOf(c3_total).toImplementation(sideEffects)); System.out.println("-- PUSH --"); - Expression totalPushUpdate = c3.deriveUpdateExpressionOf(c3_total, pushAccessor); + Expression totalPushUpdate = c3.deriveUpdateExpressionOf(c3_total, pushAccessor).getKey(); Parameter param = null; for (Parameter p: totalPushUpdate.getSubTerms(Parameter.class).values()) { if (p.equals(pPayment) || p.equals(pPoints) || p.equals(pHistory) || p.equals(pTotal)) { @@ -305,7 +305,7 @@ System.out.println("-- PULL --"); System.out.println(total.getResourceStateType().getImplementationTypeName() + " " + totalGetter.toImplementation() + "() {"); - System.out.println("\t return " + c3.deriveUpdateExpressionOf(c3_total, pullAccessor).toImplementation(sideEffects) + ";"); + System.out.println("\t return " + c3.deriveUpdateExpressionOf(c3_total, pullAccessor).getKey().toImplementation(sideEffects) + ";"); System.out.println("}"); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java b/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java index 93ef4e8..6234ba9 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java @@ -44,7 +44,7 @@ for (Channel c: model.getChannels()) { for (ChannelMember out: ((DataTransferChannel) c).getOutputChannelMembers()) { String[] sideEffects = new String[] {""}; - System.out.println("next" + out.getResource().getResourceName() + " = " + ((DataTransferChannel) c).deriveUpdateExpressionOf(out).toImplementation(sideEffects)); + System.out.println("next" + out.getResource().getLeafResourceName() + " = " + ((DataTransferChannel) c).deriveUpdateExpressionOf(out).toImplementation(sideEffects)); } }