Skip to content

Commit 7bb1d91

Browse files
committed
Fix Java codegen for arrays. Improve input codegen
1 parent d358d1f commit 7bb1d91

File tree

6 files changed

+216
-63
lines changed

6 files changed

+216
-63
lines changed

editor/src/main/scala/dev/sacode/flowrun/FlowRunEditor.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,10 @@ class FlowRunEditor(
106106
// fixed layout is when you force layout with a class
107107
// meaning not-changeable with checkboxes
108108
private val fixedLayout = flowRunElements.mountElem.classList.exists(_.startsWith("flowrun-layout"))
109-
// TODO ne removat sve nego samo neke opcije unutar...
110109

111-
if fixedLayout then flowRunElements.configWidget.querySelector(".flowrun-config-layout").remove()
110+
if fixedLayout then
111+
flowRunElements.configWidget.querySelector(".flowrun-config-layout").remove()
112+
flowRunElements.showConfigButton.remove()
112113
else updateLayout()
113114

114115
if mode.editable then

editor/src/main/scala/dev/sacode/flowrun/edit/CodeArea.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class CodeArea(
5454
val language = resolveLang(programModel.ast.config.lang)
5555
val generator = CodeGeneratorFactory(language, programModel.ast)
5656
val codeTry = generator.generate
57-
if codeTry.isFailure then println("Failed to generate code: " + codeTry.failed)
57+
if codeTry.isFailure then codeTry.failed.get.printStackTrace()
5858
codeTry match {
5959
case Success(res) =>
6060
val lh = res.stmtLineNums.getOrElse(stmtId, List.empty).mkString(",")

interpreter/shared/src/main/scala/dev/sacode/flowrun/ast/expression.scala

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ atom -> NUMBER | STRING | "true" | "false" | "null"
1919
| "(" expression ")" ;
2020
*/
2121

22-
case class Expression(boolOrComparison: BoolOrComparison, boolOrComparisons: List[BoolOrComparison])
22+
case class Expression(boolOrComparison: BoolOrComparison, boolOrComparisons: List[BoolOrComparison]) {
23+
def collectAtoms: List[Atom] =
24+
(List(boolOrComparison) ++ boolOrComparisons).flatMap(_.collectAtoms)
25+
}
2326

2427
object Expression:
2528
enum Type derives JsonRW:
@@ -72,24 +75,51 @@ object Expression:
7275
case class BoolOrComparison(
7376
boolAndComparison: BoolAndComparison,
7477
boolAndComparisons: List[BoolAndComparison]
75-
)
76-
77-
case class BoolAndComparison(numComparison: NumComparison, numComparisons: List[NumComparisonOpt])
78-
79-
case class NumComparison(term: Term, terms: Option[TermOpt])
80-
case class NumComparisonOpt(op: Token, numComparison: NumComparison)
81-
82-
case class Term(factor: Factor, factors: List[FactorOpt])
83-
case class TermOpt(op: Token, term: Term)
84-
85-
case class Factor(unary: Unary, unaries: List[UnaryOpt])
86-
case class FactorOpt(op: Token, factor: Factor)
78+
) {
79+
def collectAtoms: List[Atom] =
80+
(List(boolAndComparison) ++ boolAndComparisons).flatMap(_.collectAtoms)
81+
}
82+
83+
case class BoolAndComparison(numComparison: NumComparison, numComparisons: List[NumComparisonOpt]) {
84+
def collectAtoms: List[Atom] =
85+
numComparison.collectAtoms ++ numComparisons.flatMap(_.collectAtoms)
86+
}
87+
88+
case class NumComparison(term: Term, terms: Option[TermOpt]) {
89+
def collectAtoms: List[Atom] =
90+
term.collectAtoms ++ terms.toList.flatMap(_.collectAtoms)
91+
}
92+
case class NumComparisonOpt(op: Token, numComparison: NumComparison) {
93+
def collectAtoms: List[Atom] = numComparison.collectAtoms
94+
}
95+
96+
case class Term(factor: Factor, factors: List[FactorOpt]) {
97+
def collectAtoms: List[Atom] =
98+
factor.collectAtoms ++ factors.flatMap(_.collectAtoms)
99+
}
100+
case class TermOpt(op: Token, term: Term){
101+
def collectAtoms: List[Atom] = term.collectAtoms
102+
}
103+
104+
case class Factor(unary: Unary, unaries: List[UnaryOpt]){
105+
def collectAtoms: List[Atom] =
106+
unary.collectAtoms ++ unaries.flatMap(_.collectAtoms)
107+
}
108+
case class FactorOpt(op: Token, factor: Factor){
109+
def collectAtoms: List[Atom] = factor.collectAtoms
110+
}
87111

88112
enum Unary:
89113
case Prefixed(op: Token, unary: Unary)
90114
case Simple(atom: Atom)
91115

92-
case class UnaryOpt(op: Token, unary: Unary)
116+
def collectAtoms: List[Atom] = this match
117+
case Unary.Prefixed(op, unary) => unary.collectAtoms
118+
case Unary.Simple(atom) => List(atom)
119+
120+
case class UnaryOpt(op: Token, unary: Unary) {
121+
def collectAtoms: List[Atom] = unary.collectAtoms
122+
}
93123

94124
enum Atom:
95125
case IntegerLit(value: Int)

interpreter/shared/src/main/scala/dev/sacode/flowrun/ast/program.scala

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dev.sacode.flowrun.ast
22

33
import java.util.UUID
44
import ba.sake.tupson.*
5+
import dev.sacode.flowrun.parse.parseExpr
56

67
case class Function(
78
rawId: String,
@@ -19,7 +20,7 @@ case class Function(
1920
val title = if isMain then "main" else name
2021
val params = if isMain then "" else s"(${parameters.map(p => s"${p.name}").mkString(", ")})"
2122
s"$title$params"
22-
def verboseLabel =
23+
def verboseLabel: String =
2324
val title = if isMain then "main" else name
2425
val params = if isMain then "" else s"(${parameters.map(p => s"${p.name}: ${p.tpe}").mkString(", ")})"
2526
s"$title$params: $tpe"
@@ -41,23 +42,62 @@ case class Program(
4142
def allFunctions: List[Function] =
4243
functions.prepended(main)
4344

44-
def hasInputs: Boolean = {
45-
val allStmts = allFunctions.flatMap(_.statements).flatMap {
46-
case Statement.Block(_, blockStats) =>
47-
blockStats
48-
case stat @ Statement.If(id, expr, trueBlock, falseBlock) =>
49-
trueBlock.statements ++ falseBlock.statements
50-
case stat @ Statement.While(id, expr, body) =>
51-
body.statements
52-
case stat @ Statement.DoWhile(id, expr, body) =>
53-
body.statements
54-
case stat: Statement.ForLoop =>
55-
stat.body.statements
56-
case st =>
57-
List(st)
45+
def hasInputs: Boolean =
46+
allStmts.exists(_.isInstanceOf[Statement.Input]) ||
47+
usesFunction(PredefinedFunction.ReadInput)
48+
49+
def usesFunction(f: PredefinedFunction): Boolean =
50+
allExprs.exists{exprStr =>
51+
val expr = parseExpr("dummy", exprStr)
52+
expr.collectAtoms.exists {
53+
case fc: Atom.FunctionCall => fc.name == f.name
54+
case _=> false
55+
}
5856
}
59-
allStmts.exists(_.isInstanceOf[Statement.Input])
57+
58+
private def allStmts: Seq[Statement] = {
59+
def getStatements(s: Statement): Seq[Statement] = s match {
60+
case stmt: Statement.Block =>
61+
stmt.statements.flatMap(getStatements)
62+
case stmt: Statement.If =>
63+
getStatements(stmt.trueBlock) ++ getStatements(stmt.falseBlock)
64+
case stmt: Statement.While =>
65+
getStatements(stmt.body)
66+
case stmt: Statement.DoWhile =>
67+
getStatements(stmt.body)
68+
case stmt: Statement.ForLoop =>
69+
getStatements(stmt.body)
70+
case _ => Seq(s)
71+
}
72+
allFunctions.flatMap(_.statements).flatMap(getStatements)
6073
}
74+
75+
private def allExprs : Seq[String] = {
76+
def getExprs(s: Statement): Seq[String] = s match {
77+
case stmt: Statement.Return =>
78+
stmt.maybeValue.toSeq
79+
case stmt: Statement.Declare =>
80+
stmt.initValue.toSeq
81+
case stmt: Statement.Assign =>
82+
Seq(stmt.value)
83+
case stmt: Statement.Call =>
84+
Seq(stmt.value)
85+
case stmt: Statement.Output =>
86+
Seq(stmt.value)
87+
case stmt: Statement.Block =>
88+
stmt.statements.flatMap(getExprs)
89+
case stmt: Statement.If =>
90+
Seq(stmt.condition) ++ getExprs(stmt.trueBlock) ++ getExprs(stmt.falseBlock)
91+
case stmt: Statement.While =>
92+
Seq(stmt.condition) ++ getExprs(stmt.body)
93+
case stmt: Statement.DoWhile =>
94+
Seq(stmt.condition) ++ getExprs(stmt.body)
95+
case stmt: Statement.ForLoop =>
96+
Seq(stmt.start) ++ Seq(stmt.incr) ++ Seq(stmt.end) ++ getExprs(stmt.body)
97+
case _ => Seq.empty
98+
}
99+
allStmts.flatMap(getExprs)
100+
}
61101

62102
final case class FlowRunConfig(
63103
lang: String,

interpreter/shared/src/main/scala/dev/sacode/flowrun/codegen/CodeGenerator.scala

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@ trait CodeGenerator {
2929
protected def identPrefix: String = ""
3030

3131
private val indentAmount = 2
32-
protected var indent = 0
32+
private var indent = 0
3333

3434
private val dummyChannel = Channel[FlowRun.Event]
3535
protected val symTab = SymbolTable(dummyChannel) // needed for types of vars
3636

3737
private var lineNum = 1
38-
protected var lines = ListBuffer.empty[String]
38+
protected var lines: ListBuffer[String] = ListBuffer.empty[String]
3939
protected var stmtLineNums: mutable.Map[String, List[Int]] = mutable.Map.empty.withDefaultValue(List.empty)
4040

4141
protected def addLine(text: String): Unit =
4242
addLine(text, "")
4343
protected def addLine(text: String, stmtId: String): Unit =
4444
lines += text.indented(indent)
45-
if !stmtId.trim.isEmpty then
45+
if stmtId.trim.nonEmpty then
4646
val lineNums = stmtLineNums.getOrElse(stmtId, List.empty)
4747
stmtLineNums.put(stmtId, lineNums.appended(lineNum))
4848
lineNum += 1
@@ -57,13 +57,20 @@ trait CodeGenerator {
5757
indent -= indentAmount
5858

5959
protected def defaultValue(tpe: Type): String = tpe match {
60-
case Type.Void => ""
61-
case Type.Boolean => "false"
62-
case Type.Integer => "0"
63-
case Type.Real => "0.0"
64-
case Type.String => """ "" """.trim
60+
case Type.Void => ""
61+
case Type.Boolean => "false"
62+
case Type.Integer => "0"
63+
case Type.Real => "0.0"
64+
case Type.String => """ "" """.trim
65+
case Type.IntegerArray => sys.error(s"No default value for array or matrix")
6566
}
6667

68+
/** Parse FlowRun expression and generate real code
69+
* @param exprString
70+
* expression string to parse
71+
* @return
72+
* generated real code
73+
*/
6774
protected def parseGenExpr(exprString: String): String =
6875
genExpr(parseExpr("", exprString))
6976

@@ -126,6 +133,13 @@ trait CodeGenerator {
126133
predefFun(name, genArgs)
127134
case None =>
128135
funCall(name, genArgs)
136+
case ArrayIndexAccess(name, idxExpr) =>
137+
val idx = genExpr(idxExpr)
138+
s""" ${name}[${idx}] """
139+
case MatrixIndexAccess(name, idxExpr1, idxExpr2) =>
140+
val idx1 = genExpr(idxExpr1)
141+
val idx2 = genExpr(idxExpr2)
142+
s""" ${name}[${idx1}][${idx2}] """
129143
}
130144

131145
}

0 commit comments

Comments
 (0)