├── framework
├── supplements
│ ├── bin
│ │ └── dummy
│ ├── build.abt
│ └── subscript-supplements.iml
├── project
│ ├── build.properties
│ ├── scalajs.sbt
│ └── subscript.sbt
├── core
│ ├── shared
│ │ └── src
│ │ │ ├── main
│ │ │ └── scala
│ │ │ │ └── subscript
│ │ │ │ ├── vm
│ │ │ │ ├── executor
│ │ │ │ │ ├── parts
│ │ │ │ │ │ ├── DefaultListeners.scala
│ │ │ │ │ │ ├── TaskSupplyInterface.scala
│ │ │ │ │ │ └── Tracer.scala
│ │ │ │ │ └── data
│ │ │ │ │ │ ├── MessageHandlers.scala
│ │ │ │ │ │ └── SafeMutableState.scala
│ │ │ │ ├── model
│ │ │ │ │ ├── template
│ │ │ │ │ │ ├── OldApi.scala
│ │ │ │ │ │ ├── concrete
│ │ │ │ │ │ │ ├── Variables.scala
│ │ │ │ │ │ │ ├── SpecialOperands.scala
│ │ │ │ │ │ │ ├── ActionOperands.scala
│ │ │ │ │ │ │ └── Roots.scala
│ │ │ │ │ │ └── TreeNodes.scala
│ │ │ │ │ └── callgraph
│ │ │ │ │ │ ├── generic
│ │ │ │ │ │ ├── Informational.scala
│ │ │ │ │ │ ├── Container.scala
│ │ │ │ │ │ ├── OldApi.scala
│ │ │ │ │ │ ├── State.scala
│ │ │ │ │ │ ├── Engine.scala
│ │ │ │ │ │ ├── ExecutionResult.scala
│ │ │ │ │ │ ├── GraphNavigation.scala
│ │ │ │ │ │ ├── ListenableNode.scala
│ │ │ │ │ │ ├── ChildrenState.scala
│ │ │ │ │ │ ├── Variables.scala
│ │ │ │ │ │ └── OptionalChildrenState.scala
│ │ │ │ │ │ ├── Constants.scala
│ │ │ │ │ │ ├── concrete
│ │ │ │ │ │ ├── Variables.scala
│ │ │ │ │ │ ├── SpecialOperands.scala
│ │ │ │ │ │ ├── Communication.scala
│ │ │ │ │ │ ├── ActionOperands.scala
│ │ │ │ │ │ └── Roots.scala
│ │ │ │ │ │ └── Graph.scala
│ │ │ │ └── MsgListener.scala
│ │ │ │ ├── package.scala
│ │ │ │ └── CorePredef.scala
│ │ │ └── test
│ │ │ └── scala
│ │ │ └── subscript
│ │ │ ├── Foo.scala
│ │ │ └── Test.scala
│ ├── jvm
│ │ └── src
│ │ │ └── main
│ │ │ └── scala
│ │ │ └── subscript
│ │ │ └── vm
│ │ │ ├── ThreadedCodeFragmentExecutor.scala
│ │ │ └── executor
│ │ │ └── CommonScriptExecutor.scala
│ └── js
│ │ └── src
│ │ └── main
│ │ └── scala
│ │ └── subscript
│ │ └── vm
│ │ ├── ThreadedCodeFragmentExecutor.scala
│ │ └── executor
│ │ └── CommonScriptExecutor.scala
├── core-scripts
│ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── subscript
│ │ │ ├── SubScriptApplication.scala
│ │ │ ├── objectalgebra
│ │ │ ├── SSProcess.scala
│ │ │ └── Trigger.scala
│ │ │ ├── ScriptDSL.scala
│ │ │ └── Predef.scala
│ │ └── test
│ │ └── scala
│ │ └── subscript
│ │ ├── CommonHelpers.scala
│ │ ├── ScriptDSLSuite.scala
│ │ ├── BugsSuite.scala
│ │ ├── SubScriptSuite.scala
│ │ └── CaretSuite.scala
├── swing
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── swing
│ │ ├── FrameProcess.scala
│ │ ├── SubScriptDebugger.scala
│ │ └── PureScalaDebugger.scala
├── akka
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── subscript
│ │ └── akka
│ │ └── SubScriptActorRunner.scala
└── build.sbt
├── plugins
├── .sbtopts
├── parser
│ ├── src
│ │ ├── test
│ │ │ ├── resources
│ │ │ │ ├── test.scala
│ │ │ │ └── subscript
│ │ │ │ │ ├── examples
│ │ │ │ │ ├── helloworld-example
│ │ │ │ │ │ ├── Hello_1_World.scala
│ │ │ │ │ │ ├── Hello_1_World_rewritten.scala
│ │ │ │ │ │ ├── HelloWorld.scala
│ │ │ │ │ │ ├── update_header.sh
│ │ │ │ │ │ └── HelloWorld_rewritten.scala
│ │ │ │ │ ├── subscript-twitter-search
│ │ │ │ │ │ ├── Controller.scala
│ │ │ │ │ │ ├── update_header.sh
│ │ │ │ │ │ ├── SubScriptController.scala
│ │ │ │ │ │ ├── PureController.scala
│ │ │ │ │ │ └── SubScriptFuturesController.scala
│ │ │ │ │ ├── ab-example
│ │ │ │ │ │ ├── update_header.sh
│ │ │ │ │ │ ├── Bag_AB.scala
│ │ │ │ │ │ ├── AB.scala
│ │ │ │ │ │ ├── ABC.scala
│ │ │ │ │ │ ├── Bag.scala
│ │ │ │ │ │ ├── AB_rewritten.scala
│ │ │ │ │ │ └── Bag_AB_rewritten.scala
│ │ │ │ │ ├── life-example
│ │ │ │ │ │ ├── update_header.sh
│ │ │ │ │ │ ├── Coord.scala
│ │ │ │ │ │ ├── BasicLifeFrame.scala
│ │ │ │ │ │ └── BasicLifeFrame_rewritten.scala
│ │ │ │ │ ├── lookupframe-example
│ │ │ │ │ │ ├── update_header.sh
│ │ │ │ │ │ └── LookupFrame.scala
│ │ │ │ │ └── taskprocessor
│ │ │ │ │ │ ├── update_header.sh
│ │ │ │ │ │ ├── SSActorFamily.scala
│ │ │ │ │ │ ├── Processor.scala
│ │ │ │ │ │ ├── Proxy.scala
│ │ │ │ │ │ └── Processor_rewritten.scala
│ │ │ │ │ ├── update_header.sh
│ │ │ │ │ ├── core
│ │ │ │ │ ├── update_header.sh
│ │ │ │ │ ├── Test.scala
│ │ │ │ │ └── Test_rewritten.scala
│ │ │ │ │ ├── swing
│ │ │ │ │ ├── update_header.sh
│ │ │ │ │ ├── SubScriptDebugger.scala
│ │ │ │ │ └── SubScriptDebugger_rewritten.scala
│ │ │ │ │ └── update.sh
│ │ │ └── scala
│ │ │ │ └── scalaParser
│ │ │ │ ├── subscript
│ │ │ │ ├── IntegratedSuite.scala
│ │ │ │ ├── generic
│ │ │ │ │ ├── AspectNodeSuite.scala
│ │ │ │ │ └── CommunicationStackSuite.scala
│ │ │ │ ├── MarkerSuite.scala
│ │ │ │ ├── MigrationSuite.scala
│ │ │ │ └── Symbols.scala
│ │ │ │ └── ProjectTests.scala
│ │ └── main
│ │ │ └── scala
│ │ │ └── scalaParser
│ │ │ ├── subscript
│ │ │ ├── ast
│ │ │ │ ├── CodePrimitives.scala
│ │ │ │ ├── Core.scala
│ │ │ │ ├── UtilNodes.scala
│ │ │ │ ├── Ast.scala
│ │ │ │ └── Header.scala
│ │ │ ├── parser
│ │ │ │ ├── MarkerParser.scala
│ │ │ │ ├── SubScript.scala
│ │ │ │ ├── Header.scala
│ │ │ │ └── Core.scala
│ │ │ └── util
│ │ │ │ └── CommunicationStack.scala
│ │ │ ├── syntax
│ │ │ ├── Identifiers.scala
│ │ │ ├── Basic.scala
│ │ │ └── Literals.scala
│ │ │ ├── RulesOps.scala
│ │ │ └── Switches.scala
│ ├── submodules-clear.sh
│ ├── README.md
│ └── .gitmodules
├── project
│ └── build.properties
├── enhanced-macros
│ └── src
│ │ └── main
│ │ ├── resources
│ │ └── scalac-plugin.xml
│ │ └── scala
│ │ └── subscript
│ │ └── enhancedmacros
│ │ └── Plugin.scala
├── build.sbt
└── plugin-parser
│ └── src
│ └── main
│ └── scala
│ └── subscript
│ └── plugin
│ └── SubscriptSbt.scala
├── .gitignore
├── set_version.sh
└── count_src_lines
/framework/supplements/bin/dummy:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/framework/supplements/build.abt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/plugins/.sbtopts:
--------------------------------------------------------------------------------
1 | -J-Xss6m
2 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/test.scala:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/framework/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.9
2 |
--------------------------------------------------------------------------------
/plugins/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.9
2 |
--------------------------------------------------------------------------------
/framework/project/scalajs.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.15")
2 |
--------------------------------------------------------------------------------
/framework/project/subscript.sbt:
--------------------------------------------------------------------------------
1 | resolvers += Resolver.sonatypeRepo("snapshots")
2 | addSbtPlugin("org.subscript-lang" %% "subscript-sbt-plugin" % "3.0.5")
3 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/executor/parts/DefaultListeners.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.executor.parts
2 |
3 | import subscript.vm._
4 |
5 |
--------------------------------------------------------------------------------
/framework/core/shared/src/test/scala/subscript/Foo.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | object Foo {
4 | def main(args: Array[String]): Unit = println("Foo")
5 | }
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/package.scala:
--------------------------------------------------------------------------------
1 | package object subscript {
2 |
3 | object language {
4 | object parserSettings {}
5 | }
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/plugins/enhanced-macros/src/main/resources/scalac-plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | enhancedmacros
3 | subscript.enhancedmacros.Plugin
4 |
5 |
--------------------------------------------------------------------------------
/plugins/parser/submodules-clear.sh:
--------------------------------------------------------------------------------
1 | rm -rf scala/*
2 | rm -rf akka/*
3 | rm -rf scala-js/*
4 | rm -rf scalaz/*
5 | rm -rf shapeless/*
6 | rm -rf framework/*
7 | rm -rf playframework/*
8 |
--------------------------------------------------------------------------------
/plugins/parser/README.md:
--------------------------------------------------------------------------------
1 | SubScript parser
2 | ============
3 |
4 | A parboiled2-based parser intended for parsing of SubScript syntax.
5 | Forked from: https://github.com/lihaoyi/fastparse
6 | Original project: http://subscript-lang.org/
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | *.log
3 |
4 | # sbt specific
5 | .cache
6 | .history
7 | .lib/
8 | dist/*
9 | target/
10 | lib_managed/
11 | src_managed/
12 | project/boot/
13 | project/plugins/project/
14 |
15 | # Scala-IDE specific
16 | .scala_dependencies
17 | .worksheet
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/template/OldApi.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.template
2 |
3 | trait TemplateNodeHelpers {this: TemplateNode =>
4 | // TBD: remove asInstanceOf
5 | def hierarchyString: String = TemplateNode.hierarchyString(this, parent.asInstanceOf[TemplateNode.Parent], false)
6 | }
7 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/main/scala/subscript/SubScriptApplication.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | import subscript.objectalgebra._
4 |
5 | trait SubScriptApplication extends SSProcess {
6 |
7 | def main(args: Array[String]): Unit = {
8 | subscript.DSL._execute(lifecycle)
9 | System.exit(0)
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/main/scala/subscript/objectalgebra/SSProcess.scala:
--------------------------------------------------------------------------------
1 | package subscript.objectalgebra
2 |
3 | import subscript.language
4 |
5 | trait SSProcess {
6 |
7 | script..
8 |
9 | /** To be overriden by the user */
10 | live: Any
11 |
12 | /** Enhancements to "live" go here */
13 | lifecycle = live
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/helloworld-example/Hello_1_World.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import subscript.DSL._
5 |
6 | // Subscript sample application: Hello+(+); World
7 | //
8 | // object Hello_1_World {
9 | // def main(args: Array[String]) {_execute(live)}
10 |
11 | // script live = {println("Hello,")} + (+);
12 | // {println("world!")}
13 | // }
14 |
15 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/Informational.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.executor._
4 | import subscript.vm.model.callgraph._
5 | import subscript.DSL._
6 |
7 | trait Informational {this: CallGraphNode =>
8 | def basicInfoString = f"$index%2d $template"
9 | def infoString = basicInfoString
10 | override def toString = index+" "+template
11 | }
12 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/helloworld-example/Hello_1_World_rewritten.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import subscript.DSL._
5 |
6 | // Subscript sample application: Hello+(+); World
7 | //
8 | // object Hello_1_World {
9 | // def main(args: Array[String]) {_execute(live)}
10 |
11 | // script live = {println("Hello,")} + (+);
12 | // {println("world!")}
13 | // }
14 |
15 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/subscript-twitter-search/Controller.scala:
--------------------------------------------------------------------------------
1 | package subscript.twitter.app.controller
2 |
3 | import subscript.twitter.api.Twitter
4 | import subscript.twitter.app.view.View
5 |
6 | /**
7 | * Created by anatolii on 11/29/14.
8 | */
9 | trait Controller {
10 |
11 | val view: View
12 |
13 | val twitter = Twitter()
14 | val tweetsCount = 10
15 | val keyTypeDelay = 500
16 |
17 | def start(): Unit
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/test/scala/subscript/CommonHelpers.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | import subscript.language
4 | import subscript.Predef._
5 |
6 | import scala.util._
7 |
8 | import subscript.vm._
9 | import subscript.DSL._
10 |
11 | trait CommonHelpers {
12 | import subscript.vm._
13 | import subscript.DSL._
14 |
15 | implicit class ScriptEvaluator[T](n: Script[T]) {
16 | def e: Try[T] = _execute(n).$
17 | }
18 |
19 | script..
20 | n1 = {!1!}
21 | n2 = {!2!}
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/framework/supplements/subscript-supplements.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/ast/CodePrimitives.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.ast
2 |
3 | trait CodePrimitives {this: Ast =>
4 | def nodeToScript(name: String, node: Node): String = ScriptBody(node).compile(
5 | t2b = Map(Constants.Key.HEADER_NAME -> name)
6 | )
7 |
8 | def partialFunction(content: String) = {
9 | val defaultMatcher = """case _ => throw new RuntimeException("No suitable matcher found")"""
10 | s"""{
11 | |$content
12 | |${if (content.isEmpty) defaultMatcher else ""}
13 | |}""".stripMargin
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser"
4 | export DESTINATION="."
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 |
10 | FILES=($(ls -1 "$SOURCE/$ORIGINAL_SRC/subscript/example"))
11 |
12 | for i in ${!FILES[*]}; do
13 | FILES[i]=${FILES[i]%.*}
14 | PREFIXES[i]="subscript/example/"
15 | done
16 |
17 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
18 |
19 | # echo ${PAYLOAD[*]}
20 |
21 | ./update.sh "${PAYLOAD[*]}"
22 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/core/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/subscript/core"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/core"
5 |
6 | export ORIGINAL_SRC="src/test/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/test"
8 |
9 |
10 | FILES=(
11 | "OperatorsSuite"
12 | "Test"
13 | )
14 |
15 | for i in ${!FILES[*]}; do
16 | PREFIXES[i]="subscript/"
17 | done
18 |
19 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
20 |
21 | # echo ${PAYLOAD[*]}
22 |
23 | ../update.sh "${PAYLOAD[*]}"
24 |
--------------------------------------------------------------------------------
/framework/swing/src/main/scala/swing/FrameProcess.scala:
--------------------------------------------------------------------------------
1 | package subscript.swing
2 |
3 | import subscript.language
4 |
5 | import scala.swing.event._
6 |
7 | import subscript.Predef._
8 | import subscript.objectalgebra._
9 | import subscript.swing.Scripts._
10 |
11 |
12 | trait FrameProcess extends scala.swing.Frame with SSProcess {
13 |
14 | val closed = new Trigger
15 |
16 | override def closeOperation() {
17 | closed.trigger
18 | }
19 |
20 | implicit script vkey(??k: Key.Value) = vkey2: this, ??k
21 |
22 | override script lifecycle =
23 | @{visible=true; there.onDeactivate(close())}: super.lifecycle^ / closed
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/swing/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/subscript/swing"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/swing"
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 |
10 | FILES=(
11 | "Scripts"
12 | "SubScriptDebugger"
13 | )
14 |
15 | for i in ${!FILES[*]}; do
16 | PREFIXES[i]="swing/"
17 | done
18 |
19 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
20 |
21 | # echo ${PAYLOAD[*]}
22 |
23 | ../update.sh "${PAYLOAD[*]}"
24 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/helloworld-example/HelloWorld.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import subscript.DSL._
5 |
6 | // Subscript sample application: "Hello world!", printed using a sequence of 2 code fragments
7 |
8 | object HelloWorld {
9 | // bridge method:
10 | def main( args: Array[String]): Unit = _execute(live)
11 |
12 | // The compiler translates this internally to a method:
13 | //
14 | // def _live() = _script(this, 'main, _args~'args) {_seq({print("Hello ")}, {println("world!") })}
15 | script live = val x: Int = 3
16 | {println(x)}
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/plugins/parser/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "scala"]
2 | path = scala
3 | url = https://github.com/scala/scala
4 | [submodule "akka"]
5 | path = akka
6 | url = https://github.com/akka/akka
7 | [submodule "scala-js"]
8 | path = scala-js
9 | url = https://github.com/scala-js/scala-js
10 | [submodule "scalaz"]
11 | path = scalaz
12 | url = https://github.com/scalaz/scalaz
13 | [submodule "shapeless"]
14 | path = shapeless
15 | url = https://github.com/milessabin/shapeless
16 | [submodule "framework"]
17 | path = framework
18 | url = https://github.com/lift/framework
19 | [submodule "playframework"]
20 | path = playframework
21 | url = https://github.com/playframework/playframework
22 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/executor/data/MessageHandlers.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.executor.data
2 |
3 | import scala.collection.mutable.ListBuffer
4 | import subscript.vm._
5 | import subscript.vm.executor._
6 | import MessageHandlers._
7 |
8 | class MessageHandlers(val lock: AnyRef) extends SafeCollection[MessageHandler] {
9 |
10 | def isEmpty = collection.isEmpty
11 |
12 | val collection = ListBuffer[MessageHandler]()
13 | def insert(e: MessageHandler): Unit = collection += e
14 | def remove(e: MessageHandler): Unit = collection -= e
15 | }
16 |
17 | object MessageHandlers {
18 | type MessageHandler = PartialFunction[CallGraphMessage, Unit]
19 | }
20 |
--------------------------------------------------------------------------------
/set_version.sh:
--------------------------------------------------------------------------------
1 | VERSION=$1
2 |
3 | PATTERN_BUILD_SBT="s/(version[[:space:]]+:=[[:space:]]+)\".*\"/\1\"$VERSION\"/g"
4 |
5 | PLUGINS_BUILD="plugins/build.sbt"
6 | FRAMEWORK_BUILD="framework/build.sbt"
7 | FRAMEWORK_PLUGIN="framework/project/subscript.sbt"
8 | PLUGIN_SOURCE="plugins/plugin-parser/src/main/scala/subscript/plugin/SubscriptSbt.scala"
9 |
10 | sed -E -i '' $PATTERN_BUILD_SBT $PLUGINS_BUILD
11 | sed -E -i '' $PATTERN_BUILD_SBT $FRAMEWORK_BUILD
12 |
13 | sed -E -i '' "s/(addSbtPlugin\(\"org.subscript-lang\" %% \"subscript-sbt-plugin\" % \").*(\"\))/\1$VERSION\2/g" $FRAMEWORK_PLUGIN
14 | sed -E -i '' "s/(addCompilerPlugin\(\"org.subscript-lang\" %% \"enhancedmacros\" % \").*(\"\))/\1$VERSION\2/g" $PLUGIN_SOURCE
15 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/ab-example/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/examples/standard/ab-example"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/examples/ab-example"
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 |
10 | FILES=($(ls -1 "$SOURCE/$ORIGINAL_SRC/subscript/example"))
11 |
12 | for i in ${!FILES[*]}; do
13 | FILES[i]=${FILES[i]%.*}
14 | PREFIXES[i]="subscript/example/"
15 | done
16 |
17 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
18 |
19 | # echo ${PAYLOAD[*]}
20 |
21 | ../../update.sh "${PAYLOAD[*]}"
22 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/life-example/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/examples/standard/life-example"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/examples/life-example"
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 |
10 | FILES=($(ls -1 "$SOURCE/$ORIGINAL_SRC/subscript/example/life"))
11 |
12 | for i in ${!FILES[*]}; do
13 | FILES[i]=${FILES[i]%.*}
14 | PREFIXES[i]="subscript/example/life/"
15 | done
16 |
17 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
18 |
19 | # echo ${PAYLOAD[*]}
20 |
21 | ../../update.sh "${PAYLOAD[*]}"
22 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/lookupframe-example/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/examples/standard/lookupframe-example"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/examples/lookupframe-example"
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 |
10 | FILES=($(ls -1 "$SOURCE/$ORIGINAL_SRC/subscript/example"))
11 |
12 | for i in ${!FILES[*]}; do
13 | FILES[i]=${FILES[i]%.*}
14 | PREFIXES[i]="subscript/example/"
15 | done
16 |
17 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
18 |
19 | # echo ${PAYLOAD[*]}
20 |
21 | ../../update.sh "${PAYLOAD[*]}"
22 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/Constants.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph
2 |
3 | object ActivationMode extends Enumeration {
4 | type ActivationModeType = Value
5 | val
6 | Active,
7 | Optional,
8 | Inactive
9 | = Value
10 | }
11 |
12 | object ExecutionResult extends Enumeration {
13 | type ExecutionResultType = Value
14 | val
15 | Success,
16 | Failure,
17 | Ignore,
18 | Break,
19 | OptionalBreak
20 | = Value
21 | }
22 |
23 | object NodeStateEvent extends Enumeration {
24 | type NodeStateEvent = Value
25 | val
26 | OnActivate,
27 | OnDeactivate,
28 | OnSuspend,
29 | OnResume,
30 | OnSuccess,
31 | OnFailure,
32 | OnExclude
33 | = Value
34 | }
35 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/Container.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import scala.collection.mutable.HashMap
4 | import subscript.vm.model.callgraph.CallGraphNode
5 |
6 | trait Container {this: CallGraphNode =>
7 | private[this] val properties = new HashMap[Any,Any]
8 |
9 | def setProperty[K, V](k: K, v: V) {properties += k -> v}
10 | def getProperty[K, V](k: K): Option[V] = properties.get(k).map(_.asInstanceOf[V])
11 |
12 | def getCodeProperty(key: Any): ()=>Unit = getProperty[Any, () => Unit](key) match {
13 | case None => null
14 | case Some(cp) => cp.asInstanceOf[()=>Unit]
15 | }
16 |
17 | def setCodeProperty(key: Any, c: ()=>Unit) = setProperty(key, c)
18 | }
19 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/helloworld-example/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/examples/standard/helloworld-example"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/examples/helloworld-example"
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 |
10 | FILES=($(ls -1 "$SOURCE/$ORIGINAL_SRC/subscript/example"))
11 |
12 | for i in ${!FILES[*]}; do
13 | FILES[i]=${FILES[i]%.*}
14 | PREFIXES[i]="subscript/example/"
15 | done
16 |
17 | echo ${FILES[*]}
18 |
19 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
20 |
21 | # echo ${PAYLOAD[*]}
22 |
23 | ../../update.sh "${PAYLOAD[*]}"
24 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/taskprocessor/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/examples/standard/taskprocessor"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/examples/taskprocessor"
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 | FILES=($(ls -1 "$SOURCE/$ORIGINAL_SRC/subscript/example/taskprocessor/ssactors"))
10 |
11 | for i in ${!FILES[*]}; do
12 | FILES[i]=${FILES[i]%.*}
13 | PREFIXES[i]="subscript/example/taskprocessor/ssactors/"
14 | done
15 |
16 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
17 |
18 | # echo ${PAYLOAD[*]}
19 |
20 | ../../update.sh "${PAYLOAD[*]}"
21 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/OldApi.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.executor._
4 | import subscript.vm.model.callgraph._
5 | import subscript.DSL._
6 | import subscript.vm.CodeExecutorAdapter
7 | import subscript.vm.CodeExecutorTrait
8 |
9 | trait OldCallGraphNodeApi {this: CallGraphNode =>
10 |
11 | def forEachParent(f: Parent => Unit) = parents foreach f
12 | def forEachChild (f: Child => Unit) = children foreach f
13 |
14 | def lowestSingleCommonAncestor: CallGraphNode =
15 | if (parents.size < 2) parents.headOption.getOrElse(null)
16 | else null
17 |
18 | def adaptExecutor(ca: CodeExecutorAdapter[_,CodeExecutorTrait]): Unit =
19 | {ca.adapt(codeExecutor); codeExecutor=ca}
20 | }
21 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/subscript-twitter-search/update_header.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export SOURCE="/Users/anatolii/Projects/SubScript/examples/standard/subscript-twitter-search"
4 | export DESTINATION="/Users/anatolii/Projects/SubScript/parser-plugin/subscript-parser/src/test/resources/subscript/examples/subscript-twitter-search"
5 |
6 | export ORIGINAL_SRC="src/main/scala"
7 | export REWRITTEN_SRC="target/scala-2.11/src_managed/main"
8 |
9 |
10 | FILES=($(ls -1 "$SOURCE/$ORIGINAL_SRC/subscript/twitter/app/controller"))
11 |
12 | for i in ${!FILES[*]}; do
13 | FILES[i]=${FILES[i]%.*}
14 | PREFIXES[i]="subscript/twitter/app/controller/"
15 | done
16 |
17 | PAYLOAD=("${FILES[*]}" "${PREFIXES[*]}")
18 |
19 | # echo ${PAYLOAD[*]}
20 |
21 | ../../update.sh "${PAYLOAD[*]}"
22 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/concrete/Variables.scala:
--------------------------------------------------------------------------------
1 | // package subscript.vm.model.callgraph.concrete
2 | package subscript.vm
3 |
4 | import subscript.vm.executor._
5 | import subscript.vm.model.callgraph._
6 | import subscript.vm.model.callgraph.generic._
7 | import subscript.vm.model.template.concrete._
8 | import subscript.DSL._
9 |
10 | case class N_localvar[V](template: T_localvar[V]) extends CallGraphLeafNode
11 | {
12 | type T = T_localvar[V]
13 |
14 | override def passToBeUsedToGetVariableNamed(thatName: Symbol): Int =
15 | if (template.isLoop&&template.localVariable.name==thatName)
16 | pass-1 else pass // used in: var i=0...(i+1)
17 | }
18 |
19 | case class N_privatevar(template: T_privatevar)
20 | extends CallGraphNode
21 | with GraphLeafNode
22 | {type T = T_privatevar}
23 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/taskprocessor/SSActorFamily.scala:
--------------------------------------------------------------------------------
1 | package subscript.example.taskprocessor.ssactors
2 |
3 | import subscript.akka._
4 | import scala.concurrent.duration._
5 | import akka.actor._
6 | import subscript.example.taskprocessor.ActorFamily
7 |
8 | object SSActorFamily extends ActorFamily {
9 |
10 | var started = false
11 |
12 | def preStart() {
13 | if (!started) {
14 | SSARunnerV1Scheduler.execute(null)
15 | started = true
16 | }
17 | }
18 |
19 | def frontProcessor[Di, Df, Ri, Rf] = classOf[FrontProcessor[Di, Df, Ri, Rf]]
20 |
21 | def processor[Df, Rf] = classOf[Processor[Df, Rf] ]
22 |
23 | def proxy = classOf[Proxy ]
24 |
25 | override def toString() = "SubScript Actors"
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/update.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | PAYLOAD=($*)
4 | PAYLOAD_size=${#PAYLOAD[*]}
5 |
6 | # echo ${PAYLOAD[*]}
7 |
8 | FILES=(${PAYLOAD[*]:0:PAYLOAD_size/2})
9 | PREFIXES=(${PAYLOAD[*]:PAYLOAD_size/2})
10 |
11 | # echo ${FILES[*]}
12 | # echo ${PREFIXES[*]}
13 | # echo $PAYLOAD_size
14 |
15 | for i in ${!FILES[*]}; do
16 | file=${FILES[i]}
17 | full_file="${PREFIXES[i]}${FILES[i]}"
18 |
19 | original="$SOURCE/$ORIGINAL_SRC/$full_file.scala"
20 | rewritten="$SOURCE/$REWRITTEN_SRC/$full_file.scala"
21 |
22 | original_destination="$DESTINATION/$file.scala"
23 | rewritten_destination="$DESTINATION/${file}_rewritten.scala"
24 |
25 | echo "$original -> $original_destination; $rewritten -> $rewritten_destination"
26 |
27 | cp $original $original_destination
28 | cp $rewritten $rewritten_destination
29 | done
30 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/main/scala/subscript/objectalgebra/Trigger.scala:
--------------------------------------------------------------------------------
1 | package subscript.objectalgebra
2 |
3 | import subscript.language
4 |
5 | class Trigger extends SSProcess {
6 | var listeners = List[() => Unit]()
7 | def addListener(f: () => Unit) {listeners ::= f}
8 |
9 | private[this] var value: Any = null.asInstanceOf[Any]
10 |
11 | /** Sets the value and triggers the trigger. `v` will be return as a result value of this trigger. */
12 | def trigger(v: Any) {
13 | value = v
14 | listeners.foreach(_())
15 | }
16 |
17 | /** Triggers this trigger with `null` as a result value. */
18 | def trigger {trigger(null.asInstanceOf[Any])}
19 |
20 | override script live = @{
21 | val listener = {() => there.codeExecutor.executeAA}
22 | addListener(listener)
23 | there.onDeactivate {listeners = listeners.filter(_ != listener)}
24 | }: {.value.}
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/State.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.model.callgraph._
4 |
5 | trait State {this: CallGraphNode =>
6 | // Success flag
7 | private var _hasSuccess = false
8 | def hasSuccess = _hasSuccess
9 | def hasSuccess_=(value: Boolean) {
10 | if (_hasSuccess == value) return
11 | _hasSuccess = value
12 | //println(s"$this changesSuccess to ${hasSuccess} parent: ${if (parents.isEmpty) "-" else parents(0)}")
13 |
14 | forEachParent(p => p childChangesSuccess this)
15 | }
16 |
17 | /** Exclusion flag */
18 | var isExcluded = false
19 |
20 | def isExecuting = false
21 | var numberOfBusyActions = 0
22 | def isActionBusy = numberOfBusyActions>0
23 | var aaHappenedCount = 0
24 |
25 | var stamp = 0
26 |
27 | def asynchronousAllowed: Boolean = false
28 | }
29 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/main/scala/subscript/ScriptDSL.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | import subscript.language
4 |
5 | import subscript.vm._
6 | import subscript.vm.model.callgraph._
7 |
8 | import scala.util.Try
9 |
10 | /** Contains DSL scripts. */
11 | object ScriptDSL {
12 |
13 | def _dataflow(s: Script[Any], t: PartialFunction[Any, Script[Any]], e: PartialFunction[Throwable, Script[Any]]): Script[Any] = {
14 | var s_node: N_call[Any] = null
15 | ([do @{
16 | s_node = there.asInstanceOf[N_call[Any]]
17 | here.parent.setProperty("then", t)
18 | here.parent.setProperty("else", e)
19 | }: s then t(s_node.$success)^ else e(s_node.$failure)^
20 | ])
21 | }
22 |
23 | script..
24 | _dataflow_map[T](s: Script[Any], f: T => Any) =
25 | @{there.onSuccess {`script`.$ = there.asInstanceOf[ScriptResultHolder[Any]].$.map(r => f(r.asInstanceOf[T]))} }: s
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/Engine.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.Script
4 | import subscript.vm.executor._
5 | import subscript.vm.model.callgraph._
6 | import subscript.DSL._
7 |
8 | import subscript.vm.{CodeExecutorTrait, CodeExecutorAdapter}
9 |
10 | trait Engine {this: CallGraphNode =>
11 | var _scriptExecutor: ScriptExecutor[_] = null
12 | def scriptExecutor = _scriptExecutor
13 | def scriptExecutor_=(s: ScriptExecutor[_]) = {
14 | index = s.graph.nextNodeIndex
15 | _scriptExecutor = s
16 | }
17 |
18 | var codeExecutor: CodeExecutorTrait = null
19 |
20 | def launch(aScript: Script[_]) = {_scriptExecutor.launch(this, aScript)}
21 | }
22 |
23 | object Engine {
24 | def adaptExecutor(e: Engine, ca: CodeExecutorAdapter[_,CodeExecutorTrait]) {
25 | ca.adapt(e.codeExecutor)
26 | e.codeExecutor=ca
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/ast/Core.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.ast
2 |
3 | import scalaParser.subscript.util._
4 |
5 | trait Core {this: Ast =>
6 |
7 | type Context = Map[String, Any]
8 | type Output = CommunicationStack
9 |
10 | trait Node extends Communication {
11 | def rewrite(implicit context: Context, output: Output): String
12 | }
13 |
14 | trait LiteralNode extends Node {
15 | val content: String
16 | def rewrite(implicit context: Context, output: Output) = content
17 | }
18 |
19 | trait IdentityNode extends Node {
20 | val node: Node
21 | override def rewrite(implicit context: Context, output: Output): String = node.compile
22 | }
23 |
24 | trait WrappedNode extends Node {
25 | val node : Node
26 | val method: String
27 |
28 | override def rewrite(implicit context: Context, output: Output): String = s"$method(${node.compile})"
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/template/concrete/Variables.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.template.concrete
2 |
3 | import subscript.vm.model.template._
4 | import subscript.vm._
5 | import subscript.DSL._
6 | import subscript.vm.model.callgraph._
7 | import subscript.vm.model.callgraph.generic._
8 |
9 |
10 | case class T_localvar[V](
11 | isVal : Boolean,
12 | isLoop : Boolean,
13 | localVariable: LocalVariable[V],
14 | override val code : N_localvar[V] => V
15 | ) extends T_0_ary with TemplateCodeHolder[V,N_localvar[V]] {type N = N_localvar[V]}
16 |
17 | case class T_privatevar(name: Symbol) extends T_0_ary
18 |
19 | case class T_local_valueCode[V] (
20 | override val kind : String,
21 | localVariable: LocalVariable[V],
22 | override val code : N_localvar[V]=>V
23 | ) extends T_0_ary with TemplateCodeHolder[V,N_localvar[V]] {type N = N_localvar[V]}
24 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/ExecutionResult.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.executor._
4 | import subscript.vm.model.callgraph._
5 | import subscript.DSL._
6 |
7 | trait ExecutionResult extends State {this: CallGraphNode =>
8 | private var _result = ExecutionResult.Success; // TBD: clean this all up; hasSuccess+result is too much
9 | def result = _result
10 | /*protected*/ def result_=(value: ExecutionResult.ExecutionResultType): Unit = {
11 | _result = value
12 | //hasSuccess = value == ExecutionResult.Success
13 | }
14 | def fail = result = ExecutionResult.Failure
15 | }
16 | trait UnsureExecutionResult extends ExecutionResult {this: CallGraphNode =>
17 | def ignore = result = ExecutionResult.Ignore
18 | }
19 |
20 | trait LoopExecutionResult extends UnsureExecutionResult {this: CallGraphNode =>
21 | def break = result = ExecutionResult.Break
22 | def break_optional = result = ExecutionResult.OptionalBreak
23 | }
24 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/template/concrete/SpecialOperands.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.template.concrete
2 |
3 | import subscript.vm.model.template._
4 | import subscript.vm._
5 | import subscript.DSL._
6 | import subscript.vm.model.callgraph._
7 | import subscript.vm.model.callgraph.generic._
8 |
9 |
10 | // Loops
11 | case class T_while(override val code: N_while => Boolean)
12 | extends T_0_ary with TemplateCodeHolder[Boolean,N_while] {type N = N_while}
13 | case class T_loop () extends T_0_ary {type N = N_while}
14 |
15 | // Breaks
16 | case class T_break () extends T_0_ary {type N = N_break}
17 | case class T_optional_break () extends T_0_ary {type N = N_optional_break}
18 | case class T_optional_break_loop() extends T_0_ary {type N = N_optional_break_loop}
19 |
20 | // Constants
21 | case class T_delta () extends T_0_ary {type N = N_delta}
22 | case class T_epsilon () extends T_0_ary {type N = N_epsilon}
23 | case class T_nu () extends T_0_ary {type N = N_nu}
24 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/helloworld-example/HelloWorld_rewritten.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import subscript.DSL._
5 |
6 | // Subscript sample application: "Hello world!", printed using a sequence of 2 code fragments
7 |
8 | object HelloWorld {
9 | // bridge method:
10 | def main( args: Array[String]): Unit = _execute(live)
11 |
12 | // The compiler translates this internally to a method:
13 | //
14 | // def _live() = _script(this, 'main, _args~'args) {_seq({print("Hello ")}, {println("world!") })}
15 | def live = {
16 | val x = subscript.DSL._declare[Int](scala.Symbol("x"))
17 | subscript.DSL._script[Any](None, Symbol("live")){(_node: subscript.vm.Script[Any]) =>
18 | implicit val script = _node
19 | subscript.DSL._seq(subscript.DSL._val(x, (_node: subscript.vm.N_localvar[Int]) => {implicit val here = _node; val tr: Int = subscript.DSL._maybeVarCall("3"); tr}), subscript.DSL._normal[Any] (_node => {
20 | implicit val here = _node
21 | subscript.DSL._maybeVarCall("println(subscript.DSL._maybeVarCall(\"x\"))")
22 | }, true))}
23 |
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/core/Test.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 | import subscript.file
3 |
4 | // import org.junit.runner.RunWith
5 |
6 | import subscript.Predef._
7 | import subscript.DSL._
8 | import subscript.vm.{N_code_unsure, SimpleScriptDebugger, Script}
9 | import subscript.vm.model.callgraph._
10 | import subscript.vm.executor._
11 |
12 | class TestC {
13 |
14 | script..
15 | times(n:Int) = while(here.pass < n)
16 | key(??c: Char) = {c='!'}
17 | mainScript(args: Array[String]) = val c: Char = ' '
18 | key(?c) {println(s"key => $c")}
19 | key('!') {println("key <= '!'")}
20 |
21 | val times1: Int=>Script[Any] = n=>{_script(this, 'lambda) {script => _while{implicit here=>passScript[Any] = n=> [ while(here.pass < n) ]
23 | //val times3: Int=>Script = [ while(pass < _) ]
24 | //val noXml = [noXML]
25 |
26 | //TBD: allow ? in all parameter lists; parse < script > blocks
27 | }
28 | object Test extends TestC {
29 | // bridge method:
30 | def main( args: Array[String]): Unit = _execute(mainScript(args))
31 | }
32 |
--------------------------------------------------------------------------------
/framework/core/shared/src/test/scala/subscript/Test.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 | import subscript.language
3 |
4 | // import org.junit.runner.RunWith
5 |
6 | import subscript.CorePredef._
7 | import subscript.DSL._
8 | import subscript.vm.{N_code_unsure, SimpleScriptDebugger, Script}
9 | import subscript.vm.model.callgraph._
10 | import subscript.vm.executor._
11 |
12 | class TestC {
13 |
14 | script..
15 | times(n:Int) = while(here.pass < n)
16 | key(??c: Char) = {!c='!'!}
17 | mainScript(args: Array[String]) = val c: Char = ' '
18 | key(?c) {println(s"key => $c")}
19 | key('!') {println("key <= '!'")}
20 |
21 | val times1: Int=>Script[Any] = n=>{_script(this, 'lambda) {script => _while{implicit here=>passScript[Any] = n=> [ while(here.pass < n) ]
23 | //val times3: Int=>Script = [ while(pass < _) ]
24 | //val noXml = [noXML]
25 |
26 | //TBD: allow ? in all parameter lists; parse < script > blocks
27 | }
28 | object Test extends TestC {
29 | // bridge method:
30 | def main( args: Array[String]): Unit = _execute(mainScript(args))
31 | }
32 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/executor/parts/TaskSupplyInterface.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.executor.parts
2 |
3 | import subscript.vm._
4 | import subscript.vm.executor._
5 | import subscript.vm.executor.data._
6 | import subscript.vm.model.template._
7 | import subscript.vm.model.template.concrete._
8 | import subscript.DSL._
9 | import subscript.vm.model.callgraph.CallGraphNode
10 |
11 | trait TaskSupplyInterface {this: ScriptExecutor[_] =>
12 | def invokeFromET(f: => Unit) = msgQueue insert InvokeFromET(graph.rootNode, () => f)
13 |
14 | def launch[R](n: CallGraphNode, aScript: Script[R]) {
15 | val launchAnchor = CallGraphNode.getLowestLaunchAnchorAncestor(n) // could be rootNode
16 | val callAnchorTemplate = T_call[R]("", null)
17 | val callAnchorNode = N_call(callAnchorTemplate)
18 | CallGraph.connect(parentNode = launchAnchor, childNode = callAnchorNode, scriptNode = launchAnchor.scriptNode)
19 | CallGraph.connect(parentNode = callAnchorNode, childNode = aScript, scriptNode = launchAnchor.scriptNode) // code duplicated from Callgraph.activateFrom
20 | msgQueue insert Activation(aScript) // idem
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/MsgListener.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm
2 |
3 | import scala.collection.mutable.ListBuffer
4 |
5 | trait MsgListener {
6 | def messageHandled (m: CallGraphMessage) = {}
7 | def messageQueued (m: CallGraphMessage) = {}
8 | def messageDequeued (m: CallGraphMessage) = {}
9 | def messageContinuation(m: CallGraphMessage, c: Continuation) = {}
10 | def messageAwaiting = {}
11 |
12 | def attach(publisher: MsgPublisher) {publisher addListener this}
13 | }
14 |
15 | trait MsgPublisher extends MsgListener {
16 | private val listeners = ListBuffer[MsgListener]()
17 | def addListener (l: MsgListener) = listeners += l
18 | def removeListener(l: MsgListener) = listeners -= l
19 |
20 | override def messageHandled (m: CallGraphMessage) = listeners.foreach {_.messageHandled(m) }
21 | override def messageQueued (m: CallGraphMessage) = listeners.foreach {_.messageQueued(m) }
22 | override def messageDequeued (m: CallGraphMessage) = listeners.foreach {_.messageDequeued(m)}
23 | override def messageContinuation(m: CallGraphMessage, c: Continuation) = listeners.foreach {_.messageContinuation(m, c)}
24 | override def messageAwaiting = listeners.foreach {_.messageAwaiting}
25 | }
26 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/GraphNavigation.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm
2 | package model.callgraph
3 | package generic
4 |
5 | import subscript.vm.executor._
6 | import subscript.DSL._
7 |
8 | import subscript.vm.model.template.concrete.LogicalKind
9 |
10 | trait GraphNavigation {this: CallGraphNode =>
11 |
12 | def n_ary_op_else_ancestor: N_n_ary_op = {
13 | this match {
14 | case n:N_n_ary_op => n
15 | case _ => n_ary_op_ancestor
16 | }
17 | }
18 | // answer the n_ary_op ancestor in case there is one and the path leading thereto does not branch
19 | def n_ary_op_ancestor = if (parents.size != 1) null else parents.head.n_ary_op_else_ancestor
20 | def n_ary_op_ancestor_up(n: Int): N_n_ary_op = {
21 | var ancestor = n_ary_op_ancestor
22 | if (n<=0 || ancestor==null) return ancestor
23 | return ancestor.n_ary_op_ancestor_up(n-1)
24 | }
25 |
26 | def break_up(n: Int): Unit = {
27 | var ancestor = n_ary_op_ancestor_up(n)
28 | if (ancestor!=null) ancestor.mustBreak
29 | }
30 | def getLogicalKind_n_ary_op_ancestor: LogicalKind.LogicalKindType = {
31 | val a = n_ary_op_ancestor
32 | if (a==null) return null
33 | a.getLogicalKind
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/concrete/SpecialOperands.scala:
--------------------------------------------------------------------------------
1 | // package subscript.vm.model.callgraph.concrete
2 | package subscript.vm
3 |
4 | import subscript.vm.executor._
5 | import subscript.vm.model.callgraph._
6 | import subscript.vm.model.callgraph.generic._
7 | import subscript.vm.model.template.concrete._
8 | import subscript.DSL._
9 |
10 | // Loops
11 | case class N_while(template: T_while)
12 | extends CallGraphLeafNode
13 | {type T = T_while}
14 |
15 | case class N_loop(template: T_loop)
16 | extends CallGraphLeafNode
17 | {type T = T_loop}
18 |
19 | // Breaks
20 | case class N_break(template: T_break)
21 | extends CallGraphLeafNode
22 | {type T = T_break}
23 |
24 | case class N_optional_break(template: T_optional_break)
25 | extends CallGraphLeafNode
26 | {type T = T_optional_break}
27 |
28 | case class N_optional_break_loop(template: T_optional_break_loop)
29 | extends CallGraphLeafNode
30 | {type T = T_optional_break_loop}
31 |
32 | // Constants
33 | case class N_delta(template: T_delta)
34 | extends CallGraphLeafNode
35 | {type T = T_delta}
36 |
37 | case class N_epsilon(template: T_epsilon)
38 | extends CallGraphLeafNode
39 | {type T = T_epsilon}
40 |
41 | case class N_nu(template: T_nu)
42 | extends CallGraphLeafNode
43 | {type T = T_nu}
44 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/parser/MarkerParser.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.parser
2 |
3 | import language.implicitConversions
4 |
5 | import org.parboiled2._
6 |
7 | import scalaParser._
8 | import scalaParser.syntax._
9 |
10 | import scalaParser.subscript.ast.Constants
11 |
12 |
13 | /**
14 | * Determines whether a given file is subscript-containing or not.
15 | */
16 | class MarkerParser (input: ParserInput) extends Scala(input) {
17 |
18 | type ImportModel = String
19 |
20 | def ExtractImports: Rule1[Seq[ImportModel]] = {
21 | def Trans1: (String, Option[Seq[ImportModel]]) => Seq[ImportModel] = (_, x) => Trans2(x)
22 | def Trans2: Option[Seq[ImportModel]] => Seq[ImportModel] = _.getOrElse(Seq())
23 |
24 | def Imports: Rule1[Seq[ImportModel]] = rule { Import + SemisR0 }
25 | def TopPackageSeq: Rule1[String ] = OneOrMore(() => rule (`package` ~ QualId ~ !(WS ~ "{") ~> Concat), () => Semis)
26 | def Body : Rule1[Seq[ImportModel]] = rule( TopPackageSeq ~ (SemisR0 ~ Imports).? ~> Trans1 | Imports.? ~> Trans2 )
27 |
28 | rule( SemisR0.? ~ Body )
29 | }
30 |
31 | def Identify: Rule1[Boolean] = {
32 |
33 | def Trans1: Seq[ImportModel] => Boolean = imports => imports.exists(_ endsWith Constants.Name.FILE)
34 |
35 | rule( ExtractImports ~> Trans1 )
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/scala/scalaParser/subscript/IntegratedSuite.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript
2 |
3 | import scala.util._
4 |
5 | import org.parboiled2._
6 | import utest._
7 |
8 | import scalaParser.Scala
9 | import scalaParser.subscript.ast.Ast
10 |
11 | object IntegratedSuite extends TestSuite with Checkers with Symbols {def tests = TestSuite {'subscript {
12 |
13 | * - checkFile("core/OperatorsSuite")
14 | * - checkFile("core/Test")
15 |
16 | * - checkFile("swing/Scripts")
17 | * - checkFile("swing/SubScriptDebugger")
18 |
19 | * - checkFile("examples/helloworld-example/HelloWorld")
20 | * - checkFile("examples/helloworld-example/Hello_1_World")
21 |
22 | * - checkFile("examples/ab-example/AB")
23 | * - checkFile("examples/ab-example/Bag")
24 | * - checkFile("examples/ab-example/Bag_AB")
25 |
26 | * - checkFile("examples/life-example/BasicLifeFrame")
27 | * - checkFile("examples/life-example/LifeFrame")
28 |
29 | * - checkFile("examples/lookupframe-example/LookupFrame")
30 | * - checkFile("examples/lookupframe-example/LookupFrame2")
31 |
32 | * - checkFile("examples/subscript-twitter-search/SubScriptController")
33 | * - checkFile("examples/subscript-twitter-search/SubScriptFuturesController")
34 |
35 | * - checkFile("examples/taskprocessor/FrontProcessor")
36 | * - checkFile("examples/taskprocessor/Processor")
37 | * - checkFile("examples/taskprocessor/Proxy")
38 |
39 | }}}
40 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/test/scala/subscript/ScriptDSLSuite.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | import scala.util._
4 |
5 | import subscript.language
6 | import subscript.Predef._
7 |
8 | import org.scalatest._
9 |
10 | /** Tests the usage of the ScriptDSL methods as intended in the parser. */
11 | class ScriptDSLSuite extends FlatSpec with Matchers
12 | with CommonHelpers
13 | with ScriptDSLSuiteHelpers {
14 |
15 | "Dataflow DSL method" should "work with one 'then' clause" in {
16 | dataflowTest([success: 2 ]) shouldBe Success(2)
17 | dataflowTest([success: "2"]) shouldBe Success("2")
18 | }
19 |
20 | it should "work with exceptions" in {
21 | dataflowTest([failure: "Something went wrong!"]) shouldBe Success("Runtime Exception")
22 | }
23 |
24 | }
25 |
26 | trait ScriptDSLSuiteHelpers {this: CommonHelpers =>
27 | import subscript.vm._
28 | import subscript.DSL._
29 |
30 | // The one from the parser
31 | val sampleFunction: PartialFunction[Any, Script[Any]] = {
32 | case x: Int => [success(x)]
33 | case y: String => [success(y.toString)]
34 | }
35 |
36 | val sampleExceptionsFunction: PartialFunction[Throwable, Script[Any]] = {
37 | case e: RuntimeException => [success: "Runtime Exception"]
38 | }
39 |
40 | def dataflowTest(s: Script[Any]): Try[Any] =
41 | [ScriptDSL._dataflow(s, sampleFunction, sampleExceptionsFunction)].e
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/framework/swing/src/main/scala/swing/SubScriptDebugger.scala:
--------------------------------------------------------------------------------
1 | package subscript.swing
2 | import subscript.language
3 |
4 | import subscript.swing.Scripts._
5 | import subscript.DSL._
6 |
7 | import scala.language.implicitConversions
8 |
9 | object SubScriptDebugger extends SubScriptDebuggerApp
10 | object SubScriptDebugger2 extends SubScriptDebuggerApp {
11 | // extra singleton to allow for GraphicalDebugging the SubScriptDebuggerApp
12 | override def doesThisAllowToBeDebugged = true
13 | }
14 |
15 | class SubScriptDebuggerApp extends SimpleSubscriptApplication with GraphicalDebugger {
16 |
17 | override def live: Unit = try _execute(liveScript, debugger=null, myScriptExecutor)
18 | catch {case t:Throwable => t.printStackTrace; throw t}
19 |
20 | override def main(args: Array[String]) = super.main(args)
21 |
22 | script..
23 | liveScript = [
24 | {*awaitMessageBeingHandled(true)*}
25 |
26 | if shouldStep then [
27 | @gui: updateDisplay
28 | stepCommand || [if autoCheckBox.selected then {*waitForStepTimeout*}]
29 | ]
30 |
31 | {!messageBeingHandled(false)!}
32 | ...
33 | ]
34 | || exitDebugger
35 |
36 | stepCommand = stepButton
37 | exitCommand = exitButton
38 | exitDebugger = exitCommand @gui:{!exitConfirmed=confirmExit!} while(!exitConfirmed)
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/swing/SubScriptDebugger.scala:
--------------------------------------------------------------------------------
1 | package subscript.swing
2 | import subscript.file
3 |
4 | import subscript.swing.Scripts._
5 | import subscript.DSL._
6 |
7 | import scala.language.implicitConversions
8 |
9 | object SubScriptDebugger extends SubScriptDebuggerApp
10 | object SubScriptDebugger2 extends SubScriptDebuggerApp {
11 | // extra singleton to allow for GraphicalDebugging the SubScriptDebuggerApp
12 | override def doesThisAllowToBeDebugged = true
13 | }
14 |
15 | class SubScriptDebuggerApp extends SimpleSubscriptApplication with GraphicalDebugger {
16 |
17 | override def live: Unit = try _execute(liveScript, debugger=null, myScriptExecutor)
18 | catch {case t:Throwable => t.printStackTrace; throw t}
19 |
20 | override def main(args: Array[String]) = super.main(args)
21 |
22 | script..
23 | liveScript = (
24 | {*awaitMessageBeingHandled(true)*}
25 |
26 | if shouldStep then (
27 | @gui: {!updateDisplay!}
28 | stepCommand || (if autoCheckBox.selected then {*waitForStepTimeout*})
29 | )
30 |
31 | {messageBeingHandled(false)}
32 | ...
33 | )
34 | || exitDebugger
35 |
36 | stepCommand = stepButton
37 | exitCommand = exitButton
38 | exitDebugger = exitCommand @gui:{exitConfirmed=confirmExit} while(!exitConfirmed)
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/scala/scalaParser/subscript/generic/AspectNodeSuite.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript
2 | package generic
3 |
4 | import scala.util._
5 |
6 | import utest._
7 |
8 | import scalaParser.subscript.ast.Ast._
9 |
10 | object AspectNodeSuite extends TestSuite with Checkers with Symbols {
11 |
12 | case class RootNode(c: ChildNode) extends Node with AspectNode {
13 | val name = "root"
14 |
15 | def rewriteRaw(implicit context: Context, output: Output): String =
16 | s"My child node is ${c.compile}"
17 | }
18 |
19 | class ChildNode extends Node {
20 | def rewrite(implicit context: Context, output: Output): String = {
21 | push("root_before" -> List("hello", "world") )
22 | push("root_after" -> List("after", "aspect"))
23 | "Child Node"
24 | }
25 | }
26 |
27 |
28 | def checkStr(str1: String, str2: String): Unit =
29 | if (str1 != str2) s"""Mismatch.
30 | |--- EXPECTED ---
31 | |$str2
32 | |--- OBSERVED ---
33 | |$str1
34 | |----------------
35 | """.stripMargin
36 |
37 | def tests = TestSuite {
38 | 'subscript {
39 |
40 | * - checkStr(
41 | RootNode(new ChildNode).compile
42 | , """{
43 | | hello
44 | | world
45 | | My child node is Child Node
46 | | after
47 | | aspect
48 | }"""
49 | )
50 |
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/ListenableNode.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.model.callgraph.NodeStateEvent
4 |
5 | trait ListenableNode {this: Container =>
6 | import NodeStateEvent._
7 |
8 | def onActivate : ()=>Unit = getCodeProperty(OnActivate )
9 | def onDeactivate: ()=>Unit = getCodeProperty(OnDeactivate)
10 | def onSuspend : ()=>Unit = getCodeProperty(OnSuspend )
11 | def onResume : ()=>Unit = getCodeProperty(OnResume )
12 | def onSuccess : ()=>Unit = getCodeProperty(OnSuccess )
13 | def onFailure : ()=>Unit = getCodeProperty(OnFailure )
14 | def onExclude : ()=>Unit = getCodeProperty(OnExclude )
15 |
16 | def onActivate (c: =>Unit) = setCodeProperty(OnActivate , ()=>c)
17 | def onDeactivate(c: =>Unit) = setCodeProperty(OnDeactivate, ()=>c)
18 | def onSuspend (c: =>Unit) = setCodeProperty(OnSuspend , ()=>c)
19 | def onResume (c: =>Unit) = setCodeProperty(OnResume , ()=>c)
20 | def onSuccess (c: =>Unit) = setCodeProperty(OnSuccess , ()=>c)
21 | def onFailure (c: =>Unit) = setCodeProperty(OnFailure , ()=>c)
22 | def onExclude (c: =>Unit) = setCodeProperty(OnExclude , ()=>c)
23 |
24 | def onActivateOrResume (c: =>Unit) = {setCodeProperty(OnActivate , ()=>c); setCodeProperty(OnResume , ()=>c)}
25 | def onDeactivateOrSuspend(c: =>Unit) = {setCodeProperty(OnDeactivate, ()=>c); setCodeProperty(OnSuspend, ()=>c)}
26 | def onSuccessOrFailure (c: =>Unit) = {setCodeProperty(OnSuccess , ()=>c); setCodeProperty(OnFailure, ()=>c)}
27 | }
28 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/subscript-twitter-search/SubScriptController.scala:
--------------------------------------------------------------------------------
1 | package subscript.twitter.app.controller
2 | import subscript.file
3 |
4 | import subscript.DSL._
5 | import subscript.swing.Scripts._
6 |
7 | import subscript.twitter.api._
8 | import subscript.twitter.app.view.View
9 |
10 | /**
11 | * Created by anatolii on 11/28/14.
12 | */
13 | class SubScriptController(val view: View) extends Controller {
14 |
15 | def start() = {
16 | val executor = new subscript.vm.executor.CommonScriptExecutor[Any]
17 | val debugger = new subscript.vm.SimpleScriptDebuggerClass
18 | executor.traceLevel = 2
19 | debugger.traceLevel = 4
20 | _execute(liveScript)
21 | //_execute(_live(), debugger, executor)
22 | }
23 | //def start() = _execute(_live())
24 |
25 | def sleep(t: Long) = Thread sleep t
26 |
27 | script..
28 |
29 | //live = initialize ; mainSequence (-) / .. works as well
30 |
31 | liveScript = initialize ; (mainSequence / ..)...
32 |
33 | initialize = view.main(Array())
34 |
35 | mainSequence = anyEvent(view.searchField)
36 | waitForDelay
37 | searchTweets ~~(ts:Seq[Tweet])~~> updateTweetsView(ts)
38 | +~/~(t: Throwable )~~> setErrorMsg(t)
39 |
40 | waitForDelay = {* view.setStatus("waiting" ); sleep(keyTypeDelay) *}
41 | searchTweets = {* view.setStatus("searching"); twitter.search(view.searchField.text, tweetsCount)*}
42 |
43 | updateTweetsView(ts: Seq[Tweet]) = @gui: {view.setTweets(ts)}
44 | setErrorMsg (t : Throwable ) = @gui: {view.setError(t.toString)}
45 | }
46 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/ChildrenState.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.executor._
4 | import subscript.vm.model.callgraph._
5 | import subscript.DSL._
6 |
7 | trait ChildrenState {this: CallGraphNode =>
8 | var nActivatedChildren = 0 // i.e. including the number of already deactivated children)
9 | var nActivatedChildrenWithSuccess = 0
10 | def nActivatedChildrenWithoutSuccess = nActivatedChildren - nActivatedChildrenWithSuccess
11 | def nActiveChildren = children.size
12 | def nDeactivatedChildren = nActivatedChildren - nActiveChildren
13 |
14 | def childChangesSuccess(child: Child) = {
15 | //val old_nActivatedChildrenWithSuccess = nActivatedChildrenWithSuccess
16 | nActivatedChildrenWithSuccess += (if (child.hasSuccess) 1 else -1)
17 | //println(f"$this%-14s child $child%-14s changesSuccess to ${child.hasSuccess} nActivatedChildrenWithSuccess: $old_nActivatedChildrenWithSuccess => $nActivatedChildrenWithSuccess")
18 | }
19 |
20 | def extendedInfoString = f"$basicInfoString%.10s S=${hasSuccess} nActivated=${nActivatedChildren} (=${nActivatedChildrenWithSuccess}S+${nActivatedChildrenWithoutSuccess}N)"
21 |
22 | var aChildEndedInFailure = false
23 | def aChildEndedInSuccess = rightmostChildThatEndedInSuccess_index>=0
24 | def childThatEndedInSuccess_index(i: Int) = rightmostChildThatEndedInSuccess_index =
25 | if (rightmostChildThatEndedInSuccess_index== -1) i else scala.math.max(rightmostChildThatEndedInSuccess_index, i)
26 |
27 | var rightmostChildThatEndedInSuccess_index = -1
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/subscript-twitter-search/PureController.scala:
--------------------------------------------------------------------------------
1 | package subscript.twitter.app.controller
2 |
3 | import subscript.twitter.app.view.View
4 | import subscript.twitter.util.{InterruptableFuture, CancelException}
5 |
6 | import subscript.twitter.util.InterruptableFuture.Implicits.executionContext
7 | import scala.util.{Success, Failure}
8 |
9 | import scala.swing.{Swing, Reactor}
10 |
11 | /**
12 | * Created by anatolii on 11/29/14.
13 | */
14 | class PureController(val view: View) extends Controller with Reactor {
15 |
16 | def start() = {initialize; bindInputCallback}
17 |
18 | def initialize = view.main(Array())
19 |
20 | def bindInputCallback = {
21 | listenTo(view.searchField.keys)
22 |
23 | val fWait = InterruptableFuture {Thread sleep keyTypeDelay}
24 | val fSearch = InterruptableFuture {twitter.search(view.searchField.text, tweetsCount)}
25 |
26 | // React to the keys only if the delay between presses is >= keyTypeDelay (0.5 seconds)
27 | // Without this feature, every key typed will deplete the Twitter API calls limit.
28 | reactions += {case _ =>
29 | //fWait.execute().flatMap {case _ => fSearch.execute()}.onSuccess {case tweets => Swing.onEDT {view.setTweets(tweets)}}
30 | fWait.execute().flatMap {
31 | case _ => fSearch.execute()}.onComplete {
32 | case Success(tweets) => Swing.onEDT {view.setTweets(tweets)}
33 | case Failure(e:CancelException) => Swing.onEDT {view.setStatus("...")}
34 | case Failure(ex) => Swing.onEDT {view.setError (ex.toString)}}
35 | }
36 | }
37 |
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/template/concrete/ActionOperands.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.template.concrete
2 |
3 | import subscript.vm.model.template._
4 | import subscript.vm._
5 | import subscript.DSL._
6 | import subscript.vm.model.callgraph._
7 | import subscript.vm.model.callgraph.generic._
8 |
9 | case class T_code_normal [R](override val code: N_code_normal [R] => R, val mustPropagateResultValue: Boolean = false) extends T_code_fragment[R,N_code_normal [R]] {type N = N_code_normal [R]}
10 | case class T_code_tiny [R](override val code: N_code_tiny [R] => R, val mustPropagateResultValue: Boolean = false) extends T_code_fragment[R,N_code_tiny [R]] {type N = N_code_tiny [R]}
11 | case class T_code_threaded [R](override val code: N_code_threaded [R] => R, val mustPropagateResultValue: Boolean = false) extends T_code_fragment[R,N_code_threaded [R]] {type N = N_code_threaded [R]}
12 | case class T_code_unsure [R](override val code: N_code_unsure [R] => R, val mustPropagateResultValue: Boolean = false) extends T_code_fragment[R,N_code_unsure [R]] {type N = N_code_unsure [R]}
13 | case class T_code_eventhandling [R](override val code: N_code_eventhandling [R] => R, val mustPropagateResultValue: Boolean = false) extends T_code_fragment[R,N_code_eventhandling [R]] {type N = N_code_eventhandling [R]}
14 | case class T_code_eventhandling_loop[R](override val code: N_code_eventhandling_loop[R] => R, val mustPropagateResultValue: Boolean = false) extends T_code_fragment[R,N_code_eventhandling_loop[R]] {type N = N_code_eventhandling_loop[R]}
15 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/concrete/Communication.scala:
--------------------------------------------------------------------------------
1 | // package subscript.vm.model.callgraph.concrete
2 | package subscript.vm
3 |
4 | import subscript.vm.executor._
5 | import subscript.vm.model.callgraph._
6 | import subscript.vm.model.callgraph.generic._
7 | import subscript.vm.model.template.concrete._
8 | import subscript.DSL._
9 | import subscript.vm.model.template.TemplateNode
10 | import scala.collection.mutable.ListBuffer
11 |
12 | object Multiplicity extends Enumeration {
13 | type MultiplicityType = Value
14 | val Zero_or_One, Zero_or_More, One, One_or_More = Value
15 | }
16 | /*
17 | case class Communication(_body: N_communication => TemplateNode) {
18 | var communicatorRoles: List[CommunicatorRole] = null
19 | var template: T_communication = null
20 | def setCommunicatorRoles(crs: List[CommunicatorRole]): Unit = {
21 | var names = new ListBuffer[Symbol]
22 | communicatorRoles = crs
23 | for (cr <- crs) {
24 | cr.communication = this
25 | cr.communicator.roles += cr
26 | names += cr.communicator.name
27 | }
28 | template = T_communication(null, "comm", names)
29 | }
30 | }
31 | case class Communicator(name: Symbol) {
32 | def removePendingCall(call: N_call) {instances -= call}
33 | val instances = scala.collection.mutable.ArrayBuffer.empty[N_call]
34 | var roles = new ListBuffer[CommunicatorRole]
35 | }
36 | case class CommunicatorRole(communicator: Communicator) {
37 | var communication: Communication = null
38 | var multiplicity = Multiplicity.One
39 | var parameterNames = new ListBuffer[Symbol]
40 | def ~(s: Symbol): CommunicatorRole = {parameterNames += s; this}
41 | def ~(m: Multiplicity.MultiplicityType): CommunicatorRole = {multiplicity = m; this}
42 | }
43 | */
44 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/ab-example/Bag_AB.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import scala.swing._
5 | import scala.swing.event._
6 |
7 | import subscript.DSL._
8 |
9 | import subscript.swing.SimpleSubscriptApplication
10 | import subscript.swing.Scripts._
11 |
12 | // Subscript sample application: A..B
13 | //
14 | // Note: the main part of this source file has been manually compiled from Subscript code into plain Scala
15 |
16 | abstract class Bag_AB_Application extends SimpleSubscriptApplication {
17 | def getTitle: String
18 |
19 | val A = new Button("A") {enabled = false}
20 | val B = new Button("B") {enabled = false}
21 | val a = new Button("a") {enabled = false}
22 | val b = new Button("b") {enabled = false}
23 |
24 | val top = new MainFrame {
25 | title = getTitle
26 | location = new Point (800,0)
27 | preferredSize = new Dimension(400,70)
28 | contents = new BorderPanel {
29 | add(new FlowPanel(A, B, a, b), BorderPanel.Position.North)
30 | }
31 | }
32 | override def live = _execute(liveScript)
33 | script liveScript: Any
34 | }
35 |
36 | object Bag_A extends Bag_AB_Application {
37 | def getTitle = "Bag: live = A (live&a)"
38 |
39 | override script..
40 | liveScript = A (liveScript&a)
41 | }
42 |
43 | object Bag_AB extends Bag_AB_Application {
44 | def getTitle = "Bag: live = A (live&a) + B (live&b)"
45 |
46 | override script..
47 | liveScript = A (liveScript&a)
48 | + B (liveScript&b)
49 | }
50 |
51 | object Bag_AB_loops extends Bag_AB_Application {
52 | def getTitle = "Bag = (A a & ..) & (B b & ..)"
53 |
54 | override script..
55 | liveScript = ( A a & .. )
56 | & ( B b & .. )
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/syntax/Identifiers.scala:
--------------------------------------------------------------------------------
1 | package scalaParser
2 | package syntax
3 | import acyclic.file
4 | import org.parboiled2._
5 |
6 | trait Identifiers { self: Parser with Basic =>
7 | object Identifiers{
8 | import Basic._
9 | def Operator = rule{!Keywords ~ OpChar.+}
10 |
11 | def VarId = VarId0(true)
12 | def VarId0(dollar: Boolean) = rule( !Keywords ~ Lower ~ IdRest(dollar) )
13 | def PlainId = rule( !Keywords ~ Upper ~ IdRest(true) | VarId | Operator )
14 | def PlainIdNoDollar = rule( !Keywords ~ Upper ~ IdRest(false) | VarId0(false) | Operator )
15 | def Id = rule( !Keywords ~ PlainId | ("`" ~ noneOf("`").+ ~ "`") )
16 |
17 | def IdRest(allowDollar: Boolean) = {
18 | def SkipChar = if(allowDollar) rule("_") else rule(anyOf("_$"))
19 | def IdUnderscoreChunk = rule( zeroOrMore("_") ~ (!SkipChar ~ Letter | Digit).+ )
20 | rule( IdUnderscoreChunk.* ~ (oneOrMore("_") ~ OpChar.*).? )
21 | }
22 |
23 | def AlphabetKeywords = rule {
24 | (
25 | "abstract" | "case" | "catch" | "class" | "def" | "do" | "else" |
26 | "extends" | "false" | "finally" | "final" | "finally" | "forSome" |
27 | "for" | "if" | "implicit" | "import" | "lazy" | "match" | "new" |
28 | "null" | "object" | "override" | "package" | "private" | "protected" |
29 | "return" | "sealed" | "super" | "this" | "throw" | "trait" | "try" |
30 | "true" | "type" | "val" | "var" | "while" | "with" | "yield" | "_"
31 | ) ~ !Letter
32 | }
33 | def SymbolicKeywords = rule{
34 | (
35 | ":" | ";" | "=>" | "=" | "<-" | "<:" | "<%" | ">:" | "#" | "@" | "\u21d2" | "\u2190"
36 | ) ~ !OpChar
37 | }
38 | def Keywords = rule( AlphabetKeywords | SymbolicKeywords )
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/ab-example/AB.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import scala.swing._
5 | import scala.swing.event._
6 |
7 | import subscript.DSL._
8 |
9 | import subscript.swing.SimpleSubscriptApplication
10 | import subscript.swing.Scripts._
11 |
12 |
13 | // Subscript sample application: A..B
14 | //
15 | // Note: the main part of this source file has been manually compiled from Subscript code into plain Scala
16 |
17 |
18 | abstract class ABApplication extends SimpleSubscriptApplication {
19 | import scala.language.implicitConversions
20 |
21 | def getTitle: String
22 |
23 | val A = new Button("A") {enabled = false}
24 | val B = new Button("B") {enabled = false}
25 | val X = new Button("Exit") {enabled = false}
26 | val ABLabel = new Label("..A;B") {preferredSize = new Dimension(45,26)}
27 | val outputTA = new TextArea {editable = false}
28 |
29 | val top = new MainFrame {
30 | title = getTitle
31 | location = new Point (0,0)
32 | preferredSize = new Dimension(300,70)
33 | contents = new BorderPanel {
34 | add(new FlowPanel(A, B, X, ABLabel), BorderPanel.Position.North)
35 | }
36 | }
37 |
38 | override def live = _execute(liveScript)
39 | script liveScript: Any
40 | script..
41 | doExit = X + Key.Escape
42 |
43 | implicit script vkey(??k: Key.Value): Any = vkey2(top, ??k)
44 | }
45 |
46 | object AsBX extends ABApplication {
47 | def getTitle = "A..; B; exit"
48 | override script liveScript = A ..; B; doExit
49 | }
50 | object AsBsX extends ABApplication {
51 | def getTitle = "A..B; exit"
52 | override script liveScript = A .. B; doExit
53 | }
54 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/parser/SubScript.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.parser
2 |
3 | import language.implicitConversions
4 | import org.parboiled2._
5 | import scalaParser._
6 | import scalaParser.syntax._
7 |
8 | import scalaParser.subscript.ast.Ast
9 |
10 |
11 | /**
12 | * Parser for Scala syntax.
13 | */
14 | trait SubScript extends Core with HighPriorityRulesConversions
15 | with Header
16 | with Operators {this: Exprs =>
17 |
18 | def SubScriptCode: R1 = rule {SubScriptCodeAst ~> {n: Ast.SubScriptCode => n.compile()}}
19 |
20 | def SubScriptCodeAst: R[Ast.SubScriptCode] = {
21 |
22 | def Trans1: (Seq[String], String, Seq[Ast.ScriptDef]) => Ast.SubScriptCode =
23 | {(mod, _, defs) => Ast.SubScriptCode(mod, defs)}
24 |
25 | def Trans2: Ast.ScriptDef => Seq[Ast.ScriptDef] = x => Seq(x)
26 | def Trans3: (String, Seq[Ast.ScriptDef]) => Seq[Ast.ScriptDef] = (_, seq) => seq
27 |
28 | def Trans4: (String, Seq[String]) => Seq[String] = (head, tail) => head :: tail.toList
29 | def Trans5: Option[Seq[String]] => Seq[String] = _.getOrElse(Nil)
30 |
31 | lazy val minIndent = col + 2
32 | rule {
33 | WLR0 ~ Code {minIndent} ~ (Mod ~ (WLR0 ~ Mod).* ~> Trans4).? ~> Trans5 ~ `script` ~ (ScriptDef ~> Trans2 | `..` ~ IndentedNLSequence (() => ScriptDef, minIndent) ~> Trans3) ~> Trans1
34 | }
35 | }
36 |
37 | def ScriptDef: R[Ast.ScriptDef] = {
38 |
39 | def Trans1: (Ast.ScriptHeader, Option[Ast.Node]) => Ast.ScriptDef =
40 | (header, maybeExpr) => Ast.ScriptDef(header, maybeExpr)
41 |
42 | rule {
43 | WLR0 ~ ScriptHeader ~ (wspChR0('=') ~ ScriptBody).? ~> Trans1
44 | }
45 | }
46 |
47 | def ScriptBody: R[Ast.ScriptBody] = rule { WithScript {() => Expr9} ~> Ast.ScriptBody }
48 | }
49 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/ab-example/ABC.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 |
3 | import scala.swing._
4 | import scala.swing.event._
5 | import subscript.Predef._
6 | import subscript.swing.SimpleSubscriptApplication
7 | import subscript.swing.Scripts._
8 | import subscript._
9 | import subscript.DSL._
10 | import subscript.Predef._
11 | import subscript.vm._
12 | import subscript.vm.executor._
13 |
14 | // Subscript sample application: A..B
15 | //
16 | // Note: the main part of this source file has been manually compiled from Subscript code into plain Scala
17 |
18 | /* Doesn't work, so commented out.
19 | object ABC {
20 |
21 |
22 | // script..
23 | // a(p0: String),b(p1: String) = {println("a,b communicate: "+p0+p1)}
24 | // main(args: Array[String]) = a & b
25 | //
26 | // would be translated to 2 methods:
27 | // script method, to be called from bridge method or from other scripts
28 | // bridge method. Normally returns a ScriptExecuter;
29 | // only a "main" method with the proper parameter type has return type Unit, to serve as a program entry point
30 |
31 | val __a = _communicator('a)
32 | val __b = _communicator('b)
33 |
34 | val __a_b = _communication{(_comm: N_communication) =>
35 | val _p0 = _comm._getParameter[String]('p0)
36 | val _p1 = _comm._getParameter[String]('p1)
37 | _normal0{println("a,b communicate: "+_p0.value+_p1.value)}}
38 |
39 | _relate(__a_b, __a~'p0, __b~'p1)
40 |
41 | def _a(_p0: FormalInputParameter[String]) = _comscript(this, __a, _p0~'p0)
42 | def _b(_p1: FormalInputParameter[String]) = _comscript(this, __b, _p1~'p1)
43 |
44 | def _main(_args: FormalInputParameter[Array[String]]) = _script[Any](this, 'main, _args~'args) {script => _par(_call("a", {_a("Hello ")}), _call("b", {_b("world!")}))}
45 |
46 | def main( args: Array[String]): Unit = _execute(_main(args))
47 | }
48 | */
49 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/subscript-twitter-search/SubScriptFuturesController.scala:
--------------------------------------------------------------------------------
1 | package subscript.twitter.app.controller
2 | import subscript.file
3 |
4 | import subscript.DSL._
5 | import subscript.swing.Scripts._
6 |
7 | import subscript.twitter.api._
8 | import subscript.twitter.app.view.View
9 |
10 | import subscript.twitter.util.{InterruptableFuture, CancelException}
11 | import subscript.twitter.util.InterruptableFuture.Implicits.executionContext
12 | import scala.util.{Success, Failure}
13 |
14 | /**
15 | * Created by andre on 2/22/15.
16 | */
17 | class SubScriptFuturesController(val view: View) extends Controller {
18 | import scala.language.implicitConversions
19 |
20 | def startDebug() = {
21 | val executor = new subscript.vm.executor.CommonScriptExecutor[Any]
22 | val debugger = new subscript.vm.SimpleScriptDebuggerClass
23 | executor.traceLevel = 2
24 | debugger.traceLevel = 4
25 | _execute(liveScript, debugger, executor)
26 | }
27 | def start() = _execute(liveScript)
28 |
29 | val fWait = InterruptableFuture {Thread sleep keyTypeDelay}
30 | val fSearch = InterruptableFuture {twitter.search(view.searchField.text, tweetsCount)}
31 | val faulter = InterruptableFuture {throw new Exception("Never faulter")}
32 |
33 | implicit script f2s(intf: InterruptableFuture[_]): Any =
34 | @{intf.execute().onComplete {case aTry => there.executeForTry(aTry)}}: {. .}
35 |
36 | script..
37 |
38 | liveScript = initialize ; (mainSequence / ..)...
39 |
40 | initialize = view.main(Array[String]())
41 |
42 | mainSequence = anyEvent(view.searchField)
43 | fWait
44 | fSearch ~~(ts:Seq[Tweet])~~> updateTweetsView(ts)
45 | +~/~(t: Throwable )~~> setErrorMsg(t)
46 |
47 | updateTweetsView(ts: Seq[Tweet]) = @gui: {view.setTweets(ts)}
48 | setErrorMsg (t : Throwable ) = @gui: {view.setError(t.toString)}
49 | }
50 |
--------------------------------------------------------------------------------
/count_src_lines:
--------------------------------------------------------------------------------
1 | # Count the number of lines in SubScript source directories
2 | # Results as of 15 June 2016:
3 | #
4 | # subscript/framework/akka: 180
5 | # subscript/framework/core: 5097
6 | # subscript/framework/core-scripts: 687
7 | # subscript/framework/swing: 1252
8 | # subscript/plugins/parser: 11039
9 | # subscript/plugins/plugin-parser: 92
10 | # koans: 2023
11 | # eye-test: 679
12 | # examples/ab-example: 220
13 | # examples/filedownloader: 204
14 | # examples/helloworld-example: 46
15 | # examples/life-example: 673
16 | # examples/lookupframe-example: 233
17 | # examples/pingpong-example: 55
18 | # examples/storage: 82
19 | # examples/subscript-twitter-search: 691
20 | # examples/taskprocessor: 1210
21 |
22 | SOURCE_DIRS=
23 | SOURCE_DIRS="$SOURCE_DIRS subscript/framework/akka"
24 | SOURCE_DIRS="$SOURCE_DIRS subscript/framework/core"
25 | SOURCE_DIRS="$SOURCE_DIRS subscript/framework/core-scripts"
26 | SOURCE_DIRS="$SOURCE_DIRS subscript/framework/swing"
27 | SOURCE_DIRS="$SOURCE_DIRS subscript/plugins/parser"
28 | SOURCE_DIRS="$SOURCE_DIRS subscript/plugins/plugin-parser"
29 | SOURCE_DIRS="$SOURCE_DIRS koans"
30 | SOURCE_DIRS="$SOURCE_DIRS eye-test"
31 | SOURCE_DIRS="$SOURCE_DIRS examples/ab-example"
32 | SOURCE_DIRS="$SOURCE_DIRS examples/filedownloader"
33 | SOURCE_DIRS="$SOURCE_DIRS examples/helloworld-example"
34 | SOURCE_DIRS="$SOURCE_DIRS examples/life-example"
35 | SOURCE_DIRS="$SOURCE_DIRS examples/lookupframe-example"
36 | SOURCE_DIRS="$SOURCE_DIRS examples/pingpong-example"
37 | SOURCE_DIRS="$SOURCE_DIRS examples/storage"
38 | SOURCE_DIRS="$SOURCE_DIRS examples/subscript-twitter-search"
39 | SOURCE_DIRS="$SOURCE_DIRS examples/taskprocessor"
40 |
41 | for source_dir in $SOURCE_DIRS;
42 | do echo -n "$source_dir: "; find ../$source_dir/src -name '*.scala' -print0 | xargs -0 cat | wc -l; done
43 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/ast/UtilNodes.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.ast
2 |
3 | import scalaParser.subscript.util._
4 |
5 | trait UtilNodes {this: Ast =>
6 | import Constants.Key._
7 |
8 | trait AspectNode extends Node {
9 | val name: String
10 |
11 | def rewriteRaw(implicit context: Context, output: Output): String
12 |
13 | def rewrite(implicit context: Context, output: Output): String = {
14 | val compiled = rewriteRaw
15 |
16 | def aspect(key: String): String = output.last
17 | .get(key)
18 | .map {_.asInstanceOf[List[String]]}
19 | .getOrElse(Nil)
20 | .mkString("\n")
21 |
22 | val beforeCode = aspect(before(name))
23 | val afterCode = aspect(after (name))
24 |
25 | if (!beforeCode.isEmpty || !afterCode.isEmpty)
26 | s"""{
27 | | $beforeCode
28 | | $compiled
29 | | $afterCode
30 | |}""".stripMargin
31 | else compiled
32 | }
33 | }
34 |
35 | trait Communication {this: Node =>
36 |
37 | private var pushedValue: Option[Map[String, Any]] = None
38 |
39 | def compile(implicit t2b: Context = Map(), b2t: Output = new CommunicationStackImpl): String = {
40 | val initialSize = b2t.stack.size
41 |
42 | val compiledValue = rewrite
43 |
44 | // If something was pushed by this node, push it, otherwise push an empty map
45 | pushedValue match {
46 | case Some(v) => b2t push v
47 | case None => b2t push Map()
48 | }
49 | pushedValue = None // A single node shouldn't be compiled twice, but just in case...
50 |
51 | // Reduce, so that all the children's and this node's values get combined into one
52 | b2t.reduce(b2t.stack.size - initialSize)
53 |
54 | compiledValue
55 | }
56 |
57 | def push(m: Map[String, Any]): Unit = pushedValue = Some(m)
58 | def push(p: (String, Any) ): Unit = push(Map(p))
59 |
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/concrete/ActionOperands.scala:
--------------------------------------------------------------------------------
1 | // package subscript.vm.model.callgraph.concrete
2 | package subscript.vm
3 |
4 | import scala.util.Try
5 | import subscript.vm.executor._
6 | import subscript.vm.model.callgraph._
7 | import subscript.vm.model.callgraph.generic._
8 | import subscript.vm.model.template.concrete._
9 | import subscript.DSL._
10 |
11 | // N_code_tiny has separate failed field, since hasSuccess is often false for behaving neutrally in Or-like contexts
12 | case class N_code_tiny [R](template: T_code_tiny [R]) extends N_code_fragment[R] {type T = T_code_tiny [R]; var failed: Boolean = false;
13 | override def fail: Unit = {failed=true; super.fail}}
14 | case class N_code_normal [R](template: T_code_normal [R]) extends N_code_fragment[R] {type T = T_code_normal [R]}
15 | case class N_code_threaded [R](template: T_code_threaded[R]) extends N_code_fragment[R] {type T = T_code_threaded[R]}
16 | case class N_code_unsure [R](template: T_code_unsure [R]) extends N_code_fragment[R]
17 | with UnsureExecutionResult {type T = T_code_unsure[R] }
18 |
19 | case class N_code_eventhandling [R](template: T_code_eventhandling [R]) extends N_code_fragment[R]
20 | with UnsureExecutionResult {type T = T_code_eventhandling[R]
21 | def eventHappened = codeExecutor.executeAA
22 | // experimental
23 | def executeForTry(tryResult: Try[R]): Unit = codeExecutor.asInstanceOf[EventHandlingCodeFragmentExecutor[R]].executeForTry(tryResult)
24 | }
25 | case class N_code_eventhandling_loop[R](template: T_code_eventhandling_loop[R]) extends N_code_fragment[R]
26 | with LoopExecutionResult{type T = T_code_eventhandling_loop[R]}
27 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/executor/data/SafeMutableState.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.executor.data
2 |
3 | import scala.collection.mutable.ListBuffer
4 |
5 | /**
6 | * Represents a (not thread-safe) operation.
7 | */
8 | trait Operation {
9 | def commit(): Unit
10 | }
11 |
12 | /**
13 | * This trait represents a collection with unsafe (fast) and safe (slow)
14 | * access modes. Safety implies synchronization.
15 | * It is supposed to be used in unsafe way from only one thread;
16 | * all other threads should access it in safe manner.
17 | */
18 | trait SafeMutableState {
19 |
20 | /**
21 | * This is thread-safety stragegy implementation.
22 | */
23 | val lock: AnyRef
24 |
25 | /**
26 | * Buffer records changes that are meant for the collection. The changes
27 | * are stored in chronological order in this format.
28 | */
29 | private val buffer = ListBuffer[Operation]()
30 |
31 | /**
32 | * Safely push new operation for further execution.
33 | */
34 | def push[O <: Operation](op: O): Unit = lock.synchronized {buffer += op}
35 |
36 | /**
37 | * This operation commits recorded changes into the underlying collection.
38 | * It must be called only when `lock` is taken.
39 | */
40 | def commit() = {
41 | buffer.foreach(_.commit())
42 | buffer.clear()
43 | }
44 |
45 | def unsupportedOperation(msg: String): Nothing = throw new UnsupportedOperationException(msg)
46 | def unsupportedOperation: Nothing = unsupportedOperation("This operation is not supported")
47 |
48 | }
49 |
50 | trait SafeCollection[A] extends SafeMutableState {self =>
51 |
52 | def isEmpty: Boolean
53 |
54 | private case class Insert(e: A) extends Operation {def commit() = self insert e}
55 | private case class Remove(e: A) extends Operation {def commit() = self remove e}
56 |
57 | def insert(e: A): Unit
58 | def remove(e: A): Unit
59 |
60 | def sInsert(e: A) = this push Insert(e)
61 | def sRemove(e: A) = this push Remove(e)
62 | }
63 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/Variables.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.executor._
4 | import subscript.vm.model.callgraph._
5 | import subscript.DSL._
6 | import subscript.vm.VariableHolder
7 | import scala.collection.mutable.HashMap
8 |
9 | trait Variables {this: CallGraphNode => // TBD: change CallGraphNode into CallGraphTreeNode
10 |
11 | /** Pass flag; should possibly move elsewhere */
12 | var pass = 0
13 |
14 |
15 | def passToBeUsedToGetVariableNamed(name: Symbol) = pass
16 | def getLocalVariableHolder[V<:Any](name: Symbol): VariableHolder[V] = {
17 | //var usePass = this match {
18 | // case lvl@N_localvar_loop(_:T) if (lvl.name==name) => pass-1
19 | // case _ => pass
20 | //}
21 | // yields strange compile error message:
22 | // constructor cannot be instantiated to expected type; found : subscript.vm.N_localvar_loop[V] required: subscript.vm.CallGraphTreeNode[T]
23 | // so the following code is used instead:
24 |
25 | var usePass = passToBeUsedToGetVariableNamed(name)
26 | var result: VariableHolder[V] = null
27 | var nary = n_ary_op_ancestor
28 | while (result==null) {
29 | result = nary.getVariableHolder(name, usePass)
30 | if (result==null) {
31 | usePass = nary.pass
32 | nary = nary.n_ary_op_ancestor
33 | }
34 | }
35 | result
36 | }
37 | }
38 |
39 | trait VariablesContainer extends Variables {this: CallGraphTreeNode =>
40 | val mapNamePassToVariableHolder = new HashMap[(Symbol,Int), VariableHolder[_]]
41 |
42 | def initLocalVariable[V<:Any](name: Symbol, fromPass: Int, value: V) =
43 | mapNamePassToVariableHolder += ((name,fromPass)->new VariableHolder(value))
44 |
45 | def getVariableHolder[V<:Any](name: Symbol, fromPass: Int):VariableHolder[V] =
46 | mapNamePassToVariableHolder.get((name,fromPass)) match {
47 | case None => null
48 | case Some(v:VariableHolder[V]) => v
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/template/concrete/Roots.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.template.concrete
2 |
3 | import subscript.vm.model.template._
4 | import subscript.vm._
5 | import subscript.DSL._
6 | import TemplateNode.Child
7 | import subscript.vm.model.callgraph._
8 | import subscript.vm.model.callgraph.generic._
9 |
10 |
11 | // Local launches and calls
12 | case class T_launch(
13 | override val child0: Child
14 | ) extends T_1_ary
15 |
16 | case class T_launch_anchor(
17 | override val child0: Child
18 | ) extends T_1_ary
19 |
20 | case class T_call[R](
21 | val calleeName: String, // TBD: make symbol ?
22 | override val code : N_call[R] => Script[R],
23 | val mustPropagateResultValue: Boolean = false
24 | ) extends T_0_ary with TemplateCodeHolder[Script[R],N_call[R]] with ResultPropagator
25 |
26 | // Root script types
27 | case class T_script (
28 | override val owner : AnyRef,
29 | override val kind : String,
30 | name : Symbol
31 | ) extends TemplateNode with TreeNode_1_def with RootNode {
32 | var _child0: Child = null
33 | override def toString = name.name
34 | override def child0: Child = _child0
35 | override def children: Seq[Child] = _children
36 | var _children: Seq[Child] = null
37 | def setChild(c: Child) = {
38 | _child0 = c
39 | _children = child0::Nil
40 | TreeNode.setIndexes(this, 0, 0)
41 | }
42 |
43 | }
44 |
45 | //case class T_commscript(
46 | // override val owner : AnyRef,
47 | // override val kind : String,
48 | // communicator: Communicator
49 | //) extends TemplateNode with TreeNode_0 with RootNode {
50 | // override def toString = super.toString+" "+communicator.name.name
51 | //}
52 |
53 | //case class T_communication(
54 | // override val owner: AnyRef,
55 | // override val kind : String,
56 | // names: Seq[Symbol]
57 | //) extends TemplateNode with TreeNode_0 with RootNode {
58 | // override def toString = super.toString+" "+names.mkString(",")
59 | //}
60 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/template/TreeNodes.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.template
2 |
3 | /**
4 | * Helpers for TreeNode.
5 | */
6 | object TreeNode {
7 |
8 | def setIndexes(tn: TreeNode, startIndexInScript: Int, indexForChild: Int): Int = {
9 | tn.indexAsChild = indexForChild
10 | tn.indexInScript = startIndexInScript
11 | var result = 1
12 | var i = 0
13 | tn.children.foreach{c =>
14 | c.parent = tn.asInstanceOf[c.Parent];
15 | result += setIndexes(c, startIndexInScript + result, i)
16 | i += 1
17 | }
18 | result
19 | }
20 |
21 | }
22 |
23 | /**
24 | * Base class for all Tree nodes.
25 | */
26 | trait TreeNode {
27 | type Root <: RootNode
28 | type Parent <: TreeNode
29 | type Child <: ChildNode
30 |
31 | def root : Root
32 | def parent: Parent
33 |
34 | var indexAsChild: Int = 0
35 | var indexInScript: Int = 0
36 |
37 | def children: Seq[Child]
38 | }
39 |
40 | /**
41 | * A non-root node.
42 | */
43 | trait ChildNode extends TreeNode {
44 | def root : Root = (if (parent==null) null else parent.root).asInstanceOf[Root]
45 | var parent: Parent = null.asInstanceOf[Parent]
46 | }
47 |
48 | /**
49 | * A root node.
50 | */
51 | trait RootNode extends TreeNode {
52 | def parent = null.asInstanceOf[Parent]
53 | def root = this.asInstanceOf[Root]
54 | }
55 |
56 | /*
57 | * Differentiation of the nodes based on how many children do they contain.
58 | */
59 | trait TreeNode_0 extends TreeNode {
60 | override def children: Seq[Child] = Nil
61 | }
62 |
63 | trait TreeNode_1_def extends TreeNode_0 {
64 | def child0: Child
65 | }
66 |
67 | trait TreeNode_1 extends TreeNode_1_def {
68 | val child0: Child
69 | override val children: Seq[Child] = child0::Nil
70 | }
71 |
72 | trait TreeNode_2 extends TreeNode_1 {
73 | val child1: Child
74 | override val children: Seq[Child] = child0::child1::Nil
75 | }
76 |
77 | trait TreeNode_3 extends TreeNode_2 {
78 | val child2: Child
79 | override val children: Seq[Child] = child0::child1::child2::Nil
80 | }
81 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/syntax/Basic.scala:
--------------------------------------------------------------------------------
1 | package scalaParser
2 | package syntax
3 | import acyclic.file
4 | import org.parboiled2._
5 |
6 | trait Basic { self: Parser =>
7 | object Basic{
8 | def UnicodeEscape = rule( "\\u" ~ 4.times(HexDigit) )
9 |
10 | //Numbers and digits
11 | def HexDigit = rule( Digit | "a" - "f" | "A" - "F" )
12 | def Digit = rule( "0" - "9" )
13 | def HexNum = rule( "0x" ~ oneOrMore(HexDigit) )
14 | def DecNum = rule(oneOrMore(Digit))
15 | def Exp = rule( anyOf("Ee") ~ optional(anyOf("+-")) ~ oneOrMore(Digit) )
16 | def FloatType = rule( anyOf("FfDd") )
17 |
18 | def WSChar = rule( "\u0020" | "\u0009" )
19 | def Newline = rule( "\r\n" | "\n" )
20 | def Semi = rule( ";" | oneOrMore(Newline) )
21 | def OpChar = {
22 | // scalac 2.10 crashes if OtherOrMathSymbol below is substituted by its body
23 | // Same thing for LetterDigit, LowerChar, UpperChar
24 | def OtherOrMathSymbol = CharPredicate.from(_.getType match {
25 | case Character.OTHER_SYMBOL | Character.MATH_SYMBOL => true; case _ => false
26 | })
27 |
28 | rule { anyOf("""!#%&*+-/:<=>?@\^|~""") | OtherOrMathSymbol }
29 | }
30 | def Letter = {
31 | def LetterDigit = CharPredicate.from(c => c.isLetter | c.isDigit)
32 | rule(Upper | Lower | LetterDigit )
33 | }
34 | def Lower = {
35 | def LowerChar = CharPredicate.from(_.isLower)
36 | rule("a" - "z" | "$" | "_" | LowerChar )
37 | }
38 | def Upper = {
39 | def UpperChar = CharPredicate.from(_.isUpper)
40 | rule("A" - "Z" | UpperChar )
41 | }
42 | }
43 | /**
44 | * Most keywords don't just require the correct characters to match,
45 | * they have to ensure that subsequent characters *don't* match in
46 | * order for it to be a keyword. This enforces that rule for key-words
47 | * (W) and key-operators (O) which have different non-match criteria.
48 | */
49 | object Key {
50 | def W(s: String) = rule( str(s) ~ !(Basic.Letter | Basic.Digit) )
51 | def O(s: String) = rule( str(s) ~ !Basic.OpChar )
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/util/CommunicationStack.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.util
2 |
3 | /**
4 | * A Stack used for bottom-top communication.
5 | * Children push their messages (maps) to the parent node to the stack.
6 | * After the parent node is finished with them, they are popped,
7 | * merged with the parent's message and the resulting single message
8 | * is pushed to the stack as the parent's message to grandparent.
9 | * Every node must push exactly one message; empty map is pushed if nothing is to push.
10 | */
11 | trait CommunicationStack {
12 |
13 | /** Underlying stack. */
14 | def stack: Seq[Map[String, Any]]
15 |
16 | /** Push a new message to the stack. */
17 | def push(m: Map[String, Any]): Unit
18 |
19 | /**
20 | * Retrieves and merges the given number of messages.
21 | * back to the stack and returns the resulting CommunicationStack.
22 | * The values of the resulting map are List[Any]:
23 | * the values of different maps with same keys are collected
24 | * to the list.
25 | */
26 | def last(n: Int): Map[String, List[Any]]
27 |
28 | def last: Map[String, List[Any]] = last(1)
29 |
30 | /**
31 | * Pops given number of messages, merges them, pushes the resulting message to the stack.
32 | */
33 | def reduce(n: Int): Unit
34 |
35 | }
36 |
37 | class CommunicationStackImpl extends CommunicationStack {
38 |
39 | private[this] var _stack = List[Map[String, Any]]()
40 |
41 | def stack = _stack
42 |
43 | def push(m: Map[String, Any]) = _stack ::= m
44 |
45 | def last(n: Int) = merge(stack.take(n).reverse)
46 |
47 | def reduce(n: Int) {
48 | val payload = last(n)
49 | _stack = payload :: (stack drop n)
50 | }
51 |
52 |
53 | def merge(ms: Seq[Map[String, Any]]): Map[String, List[Any]] = {
54 | ms.foldLeft(Map[String, List[Any]]()) {(acc, next) =>
55 | (acc.toSeq ++ next.toSeq)
56 | .groupBy(_._1)
57 | .mapValues {_.map {_._2}.toList}
58 | .mapValues {_.flatMap {
59 | case x: List[_] => x
60 | case x => List(x)
61 | }
62 | }
63 | }
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/executor/parts/Tracer.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.executor.parts
2 |
3 | import subscript.vm._
4 |
5 | /**
6 | * Simple tracing and error tracking
7 | */
8 | trait Tracer {
9 | def traceLevel: Int
10 | def trace(s: => String) = if (traceLevel>0) {println(s); Console.flush}
11 | def trace_nonl(s: => String) = if (traceLevel>0) {print(s); Console.flush}
12 | def error(s: String) {throw new Exception(s)}
13 |
14 | def traceAttribute(name: => String, value: Any) = traceAttribute_internal(name, value)
15 | private def traceAttribute_internal(name: String, value: Any) = if (traceLevel>=2) println(f"$name%41s: $value")
16 | def traceAttributes(n: N_n_ary_op, str: => String) = {
17 | if (traceLevel>=2)
18 | {
19 | println(s"$str:")
20 | traceAttribute_internal("activationMode", n.activationMode)
21 | traceAttribute_internal("hadFullBreak" , n.hadFullBreak)
22 | traceAttribute_internal("nActivatedMandatoryChildren" , n.nActivatedMandatoryChildren)
23 | traceAttribute_internal("nActivatedMandatoryChildrenWithSuccess" , n.nActivatedMandatoryChildrenWithSuccess)
24 | //traceAttribute_internal("nActivatedMandatoryChildrenWithoutSuccess", n.nActivatedMandatoryChildrenWithoutSuccess)
25 | traceAttribute_internal("nActivatedOptionalChildren" , n.nActivatedOptionalChildren)
26 | traceAttribute_internal("nActivatedOptionalChildrenWithSuccess" , n.nActivatedOptionalChildrenWithSuccess)
27 | //traceAttribute_internal("nActivatedOptionalChildrenWithoutSuccess" , n.nActivatedOptionalChildrenWithoutSuccess)
28 | traceAttribute_internal("indexChild_optionalBreak_last" , n.indexChild_optionalBreak_last)
29 | traceAttribute_internal("indexChild_optionalBreak_secondLast" , n.indexChild_optionalBreak_secondLast)
30 | traceAttribute_internal("indexChild_lastActivated" , if(n.lastActivatedChild==null)"" else n.lastActivatedChild.index)
31 | traceAttribute_internal("aaActivated_notBeforeLastOptionalBreak" , n.aaActivated_notBeforeLastOptionalBreak)
32 | traceAttribute_internal("aaHappenedInOptionalChildren" , n.aaHappenedInOptionalChildren)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/test/scala/subscript/BugsSuite.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | import scala.util._
4 |
5 | import subscript.language
6 | import subscript.Predef._
7 |
8 | import org.scalatest._
9 |
10 | class BugsSuite extends FlatSpec with Matchers
11 | with CommonHelpers {
12 |
13 | "#26" should "work" in {
14 | var i = 0
15 | script foo = {!i += 1!};
16 | {!i += 1!}
17 |
18 | runScript(foo)
19 |
20 | i shouldBe 2
21 | }
22 |
23 | "#28" should "work" in {
24 | script s = [^1^^1 ^2^^2]^^
25 | runScript(s).$ shouldBe Success(List((1, 2)))
26 | }
27 |
28 | "#29" should "be possible to call nice while with prefixed simple expression" in {
29 | var i = 0
30 | script s = var flag = false
31 | [while !flag {!i += 1!} {!if (i >= 3) flag = true!}]
32 |
33 | runScript(s)
34 | i shouldBe 3
35 | }
36 |
37 | it should "be possible to use prefixed expressions in nice script calls" in {
38 | script..
39 | a(x: Boolean) = if x then ^1 else ^2
40 | b = a: !true
41 |
42 | runScript(b).$ shouldBe Success(2)
43 | }
44 |
45 | it should "be possible to write if guards for actual constrained parameters" in {
46 | script..
47 | f(??x: Int) = let x = 3
48 | live =
49 | var x = 0
50 | f: ?x ?if (x > (0))
51 | ^x
52 |
53 | runScript(live).$ shouldBe Success(3)
54 | }
55 |
56 | it should "be possible to use Smalltalk-like script calls" in {
57 | script..
58 | fooBar(x: Int, y: Int) = ^(x + y)
59 | live = foo: 1, bar: 2
60 |
61 | runScript(live).$ shouldBe Success(3)
62 | }
63 |
64 | it should "be possible to use nested nice calls" in {
65 | def square(x: Int) = x * x
66 |
67 | script..
68 | fooBar(x: Int, y: Int) = ^(x + y)
69 | live = foo: square: square: 2, bar: square: square: square: square: 2
70 |
71 | runScript(live).$ shouldBe Success(65552)
72 | }
73 |
74 | "#39" should "work" in {
75 | def ifZeroThenDoElseDo(a: Int, b: Int, c: Int) = if (a == 0) b else c
76 |
77 | script s2(i: Int) = ^ifZero: i , thenDo: 1, elseDo: 2
78 |
79 | runScript(s2(0)).$ shouldBe Success(1)
80 | runScript(s2(1)).$ shouldBe Success(2)
81 | }
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/life-example/Coord.scala:
--------------------------------------------------------------------------------
1 | package subscript.example.life
2 |
3 | import scala.language.implicitConversions
4 |
5 | /*
6 | * Copied from http://rosettacode.org/wiki/Conway's_Game_of_Life/Scala
7 | */
8 | class Coord private (val x: Int, val y: Int) {
9 | private val offsets = List(-1, 0, 1)
10 | private def offsetsOf(n: Int) = offsets map (_ + n)
11 |
12 | /**
13 | * A memoized list of all neighbors of a coordinate
14 | */
15 | lazy val neighbors = for {
16 | xn <- offsetsOf(x) if Coord.legal(xn)
17 | yn <- offsetsOf(y) if Coord.legal(yn) && (x, y) != (xn, yn)
18 | } yield Coord(xn, yn)
19 |
20 | // Coordinates can be used as offsets
21 | def +(c: Coord) = Coord(x + c.x, y + c.y)
22 | def -(c: Coord) = Coord(x - c.x, y - c.y)
23 |
24 | override def equals(other: Any) = other match {
25 | case that: Coord => this.x == that.x && this.y == that.y
26 | case _ => false
27 | }
28 | override def hashCode = ((x * 41) + y) * 41 + 41
29 | override def toString = "Coord(%d, %d)" format (x, y)
30 | }
31 |
32 | object Coord {
33 | // A Conway board is infinite in size; throw an exception if our hard limits are reached
34 | private def legal(n: Int) = {
35 | n.ensuring(Int.MinValue < _, "Coord too low").ensuring(_ < Int.MaxValue, "Coord too high")
36 | true
37 | }
38 | private val cache = new scala.collection.mutable.HashMap[(Int,Int), Coord]
39 |
40 | /**
41 | * Factory for coordinates. All coordinates are memoized.
42 | */
43 | def apply(x: Int, y: Int) = {
44 | require(legal(x) && legal(y))
45 | cache getOrElseUpdate ((x,y), new Coord(x, y))
46 | }
47 |
48 | /**
49 | * Coordinate extractor
50 | */
51 | def unapply(c: Coord) = Some((c.x, c.y))
52 |
53 | /**
54 | * An Ordering for coordinates which sorts by the X coordinate
55 | */
56 | val xOrdering = Ordering.fromLessThan((_: Coord).x < (_: Coord).x)
57 |
58 | /**
59 | * An Ordering for coordinates which sorts by the Y coordinate
60 | */
61 | val yOrdering = Ordering.fromLessThan((_: Coord).y < (_: Coord).y)
62 |
63 | /**
64 | * Any Tuple2[Int, Int] can be used as a Coordinate through this implict
65 | * conversion.
66 | */
67 | implicit def coordFromTuple(t: (Int, Int)) = apply(t._1, t._2)
68 | }
69 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/Graph.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph
2 |
3 | import scala.collection.mutable.ListBuffer
4 |
5 | /**
6 | * A graph node. It can have parents of type Parent and children
7 | * of type Child.
8 | */
9 | trait GraphNode {
10 | type Child <: GraphNode
11 | type Parent <: GraphNode
12 |
13 | def children: Seq[Child ] = _children
14 | def parents : Seq[Parent] = _parents
15 |
16 | private val _children = new ListBuffer[Child ]
17 | private val _parents = new ListBuffer[Parent]
18 |
19 | /**
20 | * Links a new parent to this node. This will result
21 | * to this node being registered as a child within
22 | * the argument.
23 | */
24 | def addParent(p: Parent) {p addChild this.asInstanceOf[p.Child]}
25 |
26 | /**
27 | * Unlinks the parent.
28 | */
29 | def removeParent(p: Parent) {if (p!=null)/*test should not be needed*/ p removeChild this.asInstanceOf[p.Child]}
30 |
31 | /**
32 | * Links a new child.
33 | */
34 | def addChild(c: Child) {
35 | _children += c
36 | c._parents += this.asInstanceOf[c.Parent]
37 | }
38 |
39 | def removeFrom[T<:AnyRef](lb: ListBuffer[T], elt: T) {
40 | // lb -= elt
41 | // not applicable for nodes since these are case classes with a too generous Equals method.
42 | // use eq() instead
43 | val indexToRemove = lb.indexWhere(_.eq(elt))
44 | lb.remove(indexToRemove)
45 | }
46 | /**
47 | * Unlinks the child.
48 | */
49 | def removeChild(c: Child) {
50 | //_children -= c
51 | //c._parents -= this.asInstanceOf[c.Parent]
52 | removeFrom(_children , c)
53 | removeFrom(c._parents, this.asInstanceOf[c.Parent])
54 | }
55 | }
56 |
57 | /**
58 | * Graph node with only one parent. Any attempt to add a second parent
59 | * will result in current parent being removed.
60 | */
61 | trait GraphTreeNode extends GraphNode {
62 | def parent: Parent = parents.headOption getOrElse null.asInstanceOf[Parent]
63 |
64 | override def addParent(p: Parent) {
65 | if (parent ne null) removeParent(parent)
66 | super.addParent(p)
67 | }
68 | }
69 |
70 | /**
71 | * Graph tree node that can't have children.
72 | */
73 | trait GraphLeafNode extends GraphTreeNode {
74 | override def addChild(c: Child) = throw new RuntimeException("This node can't have children")
75 | }
76 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/scala/scalaParser/subscript/generic/CommunicationStackSuite.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript
2 | package generic
3 |
4 | import scala.util._
5 |
6 | import utest._
7 |
8 | import scalaParser.subscript.ast.Ast._
9 | import scalaParser.subscript.util._
10 |
11 | object CommunicationStackSuite extends TestSuite
12 | with Checkers
13 | with CommunicationStackSuiteHelpers {
14 | import CSSHImplicits._
15 |
16 | def tests = TestSuite {
17 | 'communicationStack {
18 |
19 | // push
20 | * - stackFull(1) {s =>
21 | s.stack.size shouldBe 1
22 | s.stack.head shouldBe map(1)
23 | }
24 |
25 | // FIFO
26 | * - stackFull(2) {s =>
27 | s.stack.size shouldBe 2
28 | s.stack(0) shouldBe map(2)
29 | s.stack(1) shouldBe map(1)
30 | }
31 |
32 | // last
33 | * - stackFull(2) {s =>
34 | s.last(2) shouldBe map(1).merge(map(2))
35 | }
36 |
37 | // reduce
38 | * - stackFull(2) {s =>
39 | s.reduce(2)
40 | s.stack.size shouldBe 1
41 | s.stack.head shouldBe map(1).merge(map(2))
42 | }
43 |
44 | // merge test
45 | * - stack {s =>
46 | s push Map("a" -> 1, "b" -> 2)
47 | s push Map("a" -> 1, "c" -> 3)
48 | s push Map("a" -> 3, "b" -> 4)
49 |
50 | s.last(3) shouldBe Map("a" -> List(1, 1, 3), "b" -> List(2, 4), "c" -> List(3))
51 | }
52 |
53 | }
54 | }
55 |
56 | }
57 |
58 | trait CommunicationStackSuiteHelpers {
59 |
60 | def newStack: CommunicationStack = new CommunicationStackImpl
61 |
62 | def stack(f: CommunicationStack => Unit): Unit = f(newStack)
63 |
64 | def stackFull(size: Int)(f: CommunicationStack => Unit): Unit = stack {s =>
65 | for (n <- 1 to size) s push map(n)
66 | f(s)
67 | }
68 |
69 | def map(x: Int): Map[String, Any] = Map(s"SAMPLE$x" -> x)
70 |
71 |
72 | object CSSHImplicits {
73 | implicit class MapRefinements[K, V](m: Map[K, V]) {
74 | def merge(another: Map[K, V]): Map[K, List[V]] = (m.toSeq ++ another.toSeq)
75 | .groupBy(_._1)
76 | .mapValues {_.map(_._2).toList}
77 |
78 | }
79 |
80 | implicit class InfixMatcher(x: Any) {
81 | def shouldBe(y: Any) =
82 | if (x != y) throw new RuntimeException(s"${x.toString} is not ${y.toString}")
83 | }
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/ab-example/Bag.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import scala.swing._
5 | import scala.swing.event._
6 |
7 | import subscript.DSL._
8 |
9 | import subscript.swing.SimpleSubscriptApplication
10 | import subscript.swing.Scripts._
11 |
12 | // Subscript sample application: a parallel recursive implementation of a Bag
13 | //
14 | // Note: the main part of this source file has been manually compiled from Subscript code into plain Scala
15 | //
16 |
17 | object Bag extends BagApplication
18 |
19 | class BagApplication extends SimpleSubscriptApplication {
20 |
21 | val lA = new Label("A") {preferredSize = new Dimension(26,26)}
22 | val lB = new Label("B") {preferredSize = new Dimension(26,26)}
23 | val pA = new Button("+") {enabled = false}
24 | val pB = new Button("+") {enabled = false}
25 | val mA = new Button("-") {enabled = false}
26 | val mB = new Button("-") {enabled = false}
27 | val cA = new Label("") {preferredSize = new Dimension(45,26)}
28 | val cB = new Label("") {preferredSize = new Dimension(45,26)}
29 | val X = new Button("Exit") {enabled = false}
30 | val bagLabel = new Label("Bag") {preferredSize = new Dimension(45,26)}
31 | val outputTA = new TextArea {editable = false}
32 |
33 |
34 | val top = new MainFrame {
35 | title = "Bag - Subscript"
36 | location = new Point (0,0)
37 | preferredSize = new Dimension(300,300)
38 | contents = new BorderPanel {
39 | //add(new FlowPanel(bagLabel, X), BorderPanel.Position.North)
40 | add(new FlowPanel(lA, pA, mA, cA), BorderPanel.Position.North)
41 | add(new FlowPanel(lB, pB, mB, cB), BorderPanel.Position.Center)
42 | add(outputTA, BorderPanel.Position.South)
43 | }
44 | }
45 | var ca = 0
46 | var cb = 0
47 | def dA(d: Int) = {ca+=d; cA.text = ca.toString}
48 | def dB(d: Int) = {cb+=d; cB.text = cb.toString}
49 | override def live = _execute(liveScript)
50 |
51 | override script
52 | liveScript = bag
53 | script ..
54 | bag: Any = A (bag&ax)
55 | + B (bag&bx)
56 |
57 | A = pA @gui:{!dA(+1)!}
58 | ax = mA @gui:{!dA(-1)!}
59 | B = pB @gui:{!dB(+1)!}
60 | bx = mB @gui:{!dB(-1)!}
61 | }
62 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/RulesOps.scala:
--------------------------------------------------------------------------------
1 | package scalaParser
2 |
3 | import org.parboiled2._
4 |
5 | import shapeless._
6 |
7 | trait RulesOps
8 | extends StringRulesOps
9 | with Metarules
10 | {this: Parser =>}
11 |
12 | trait StringRulesOps extends StringTransformFunctions {this: Parser with Metarules =>
13 |
14 | def OneOrMore(term: () => Rule1[String], delim: () => Rule1[String]): Rule1[String] = {
15 | def Factory: ((String, Seq[(String, String)])) => String = {case (head, tail) =>
16 | head + tail.map {case (a, b) => a + b}.mkString
17 | }
18 |
19 | rule {OneOrMoreSeq(term, delim) ~> Factory}
20 | }
21 |
22 | def ZeroOrMore(term: () => Rule1[String], delim: () => Rule1[String]): Rule1[String] = rule {
23 | OneOrMore(term, delim).? ~> ExtractOpt
24 | }
25 |
26 | }
27 |
28 | trait StringTransformFunctions {
29 | type S = String
30 |
31 | def Concat : (S, S) => S = _+_
32 | def Concat3: (S, S, S) => S = _+_+_
33 | def Concat4: (S, S, S, S) => S = _+_+_+_
34 | def Concat5: (S, S, S, S, S) => S = _+_+_+_+_
35 | def Concat6: (S, S, S, S, S, S) => S = _+_+_+_+_+_
36 | def Concat7: (S, S, S, S, S, S, S) => S = _+_+_+_+_+_+_
37 |
38 | def ConcatSeq(delimiter: String): (Seq[String]) => String = _.mkString(delimiter)
39 |
40 | def ConcatSeqSemi = ConcatSeq(";")
41 | def ConcatSeqNoDelim = ConcatSeq("" )
42 | def ConcatSeqComma = ConcatSeq(",")
43 | def ConcatSeqDot = ConcatSeq(".")
44 | def ConcatSeqWith = ConcatSeq(" with ")
45 | def ConcatSeqPipe = ConcatSeq("|")
46 |
47 | def ExtractOpt: Option[String] => String = _.getOrElse("")
48 |
49 | def SecondStr: (S, S) => S = (a: S, b: S) => b
50 | }
51 |
52 | trait Metarules {this: Parser =>
53 |
54 | def OneOrMoreSeq[A, B](term: () => Rule1[A], delim: () => Rule1[B]): Rule1[(A, Seq[(B, A)])] =
55 | rule ( term() ~ (delim() ~ term() ~> {(b: B, a: A) => b -> a}).* ~> {(a: A, others: Seq[(B, A)]) => a -> others} )
56 |
57 | def ZeroOrMoreSeq[A, B](term: () => Rule1[A], delim: () => Rule1[B]): Rule1[Option[(A, Seq[(B, A)])]] =
58 | rule ( OneOrMoreSeq(term, delim).? )
59 |
60 | def Code(code: => Unit): Rule0 = {code; MATCH}
61 |
62 | def Try[T](rle: () => Rule1[T], before: => Unit, after: => Unit = (), rollback: => Unit = ()): Rule1[T] = rule (
63 | Code(before ) ~ rle() ~ Code(after)
64 | | Code(rollback) ~ MISMATCH[HNil, T :: HNil]
65 | )
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/framework/core/jvm/src/main/scala/subscript/vm/ThreadedCodeFragmentExecutor.scala:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of Subscript - an extension of the Scala language
3 | with constructs from Process Algebra.
4 |
5 | Subscript is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License and the
7 | GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Subscript consists partly of a "virtual machine". This is a library;
12 | Subscript applications may distribute this library under the
13 | GNU Lesser General Public License, rather than under the
14 | GNU General Public License. This way your applications need not
15 | be made Open Source software, in case you don't want to.
16 |
17 | Subscript is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You may have received a copy of the GNU General Public License
23 | and the GNU Lesser General Public License along with Subscript.
24 | If not, see
25 | */
26 |
27 | package subscript.vm
28 |
29 | import scala.util.{Try, Failure}
30 | import scala.collection.mutable._
31 | import subscript.vm.executor._
32 | import subscript.vm.model.callgraph._
33 | import subscript.vm.model.template.TemplateCodeHolder
34 |
35 | import scala.language.existentials
36 |
37 |
38 | class ThreadedCodeFragmentExecutor[R](n: N_code_threaded[R], scriptExecutor: ScriptExecutor[_]) extends NormalCodeFragmentExecutor[R](n, scriptExecutor) {
39 | override def interruptAA: Unit = if (myThread!=null) try myThread.interrupt catch {case _: InterruptedException =>} // Don't pollute the outout
40 | regardStartAndEndAsSeparateAtomicActions = true
41 | var myThread: Thread = null
42 |
43 | override def doCodeExecutionIn(lowLevelCodeExecutor: CodeExecutorTrait): Unit = {
44 | val runnable = new Runnable {
45 | def run() {
46 | ThreadedCodeFragmentExecutor.super.doCodeExecutionIn(lowLevelCodeExecutor) // does scriptExecutor.insert(CFExecutionFinished)
47 | }
48 | }
49 | myThread = new Thread(runnable)
50 | myThread.start()
51 | }
52 | }
--------------------------------------------------------------------------------
/framework/akka/src/main/scala/subscript/akka/SubScriptActorRunner.scala:
--------------------------------------------------------------------------------
1 | package subscript.akka
2 | import subscript.language
3 |
4 | import subscript.DSL._
5 | import scala.collection.mutable.ListBuffer
6 | import subscript.vm._
7 | import subscript.vm.executor._
8 | import akka.actor._
9 |
10 | import scala.concurrent.ExecutionContext.Implicits.global
11 | import scala.concurrent.duration._
12 |
13 | import scala.language.postfixOps
14 |
15 |
16 | trait SubScriptActorRunner {
17 |
18 | def launch(s: Script[_])
19 |
20 | def execute(debugger: MsgListener)
21 |
22 | def system: ActorSystem
23 |
24 | def executor: CommonScriptExecutor[_]
25 |
26 | def doScriptSteps
27 |
28 | }
29 |
30 | object SSARunnerV1Scheduler extends SubScriptActorRunner {
31 |
32 | // Don't do heavy operations until needed
33 | lazy val system = ActorSystem()
34 | lazy val executor = ScriptExecutorFactory.createScriptExecutor[Any](true)
35 |
36 | var launch_anchor: N_launch_anchor = null
37 |
38 | def scheduledTaskDelay = 1 milliseconds
39 |
40 | def launch(s: Script[_]) = executor.invokeFromET {launch_anchor.launch(s)}
41 |
42 | script..
43 | // make a local anchor for launched actor processes,
44 | // so that we will be able to kill those here using the || and / operators
45 | live = @{launch_anchor=there.asInstanceOf[N_launch_anchor]}: [** {. .} **]
46 |
47 | def execute(debugger: MsgListener) {
48 | if (debugger!=null) debugger.attach(executor)
49 | executor.addHandler(synchMsgHandler)
50 | executor.initializeExecution(live)
51 | doScriptSteps_loop
52 | // executor run _live()
53 | }
54 |
55 | def doScriptSteps_loop: Unit = {
56 | doScriptSteps
57 | if (executor.hasActiveProcesses) {
58 | try system.scheduler.scheduleOnce(scheduledTaskDelay)(doScriptSteps_loop)
59 | catch {case _: IllegalStateException =>} // Ignore certain things...
60 | }
61 | }
62 |
63 | def doScriptSteps = {
64 | executor.updateCollections()
65 | var handledMessage = executor.tryHandleMessage(minimalPriorityForAA = Int.MinValue)
66 | while (handledMessage!=null) {
67 | executor.updateCollections()
68 | handledMessage = executor.tryHandleMessage(minimalPriorityForAA = Int.MinValue)
69 | }
70 | executor.messageAwaiting
71 | }
72 |
73 | val synchMsgHandler: PartialFunction[CallGraphMessage, Unit] = {
74 | case SynchronizationMessage(_, lock) => lock.synchronized(lock.notify())
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/framework/core/js/src/main/scala/subscript/vm/ThreadedCodeFragmentExecutor.scala:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of Subscript - an extension of the Scala language
3 | with constructs from Process Algebra.
4 |
5 | Subscript is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License and the
7 | GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Subscript consists partly of a "virtual machine". This is a library;
12 | Subscript applications may distribute this library under the
13 | GNU Lesser General Public License, rather than under the
14 | GNU General Public License. This way your applications need not
15 | be made Open Source software, in case you don't want to.
16 |
17 | Subscript is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You may have received a copy of the GNU General Public License
23 | and the GNU Lesser General Public License along with Subscript.
24 | If not, see
25 | */
26 |
27 | package subscript.vm
28 |
29 | import scala.util.{Try, Failure}
30 | import scala.collection.mutable._
31 | import subscript.vm.executor._
32 | import subscript.vm.model.callgraph._
33 | import subscript.vm.model.template.TemplateCodeHolder
34 |
35 | import scala.language.existentials
36 |
37 |
38 | class ThreadedCodeFragmentExecutor[R](n: N_code_threaded[R], scriptExecutor: ScriptExecutor[_]) extends NormalCodeFragmentExecutor[R](n, scriptExecutor) {
39 | // TODO: Copied from the Normal code fragment execution to avoid threading.
40 |
41 | override def executeAA(lowLevelCodeExecutor: CodeExecutorTrait): Unit = {
42 | super.executeAA(lowLevelCodeExecutor)
43 | if (regardStartAndEndAsSeparateAtomicActions) aaHappened(DurationalCodeFragmentStarted)
44 | doCodeExecutionIn(lowLevelCodeExecutor)
45 | }
46 | override def afterExecuteAA_internal = {
47 | if (!n.isExcluded) {
48 | aaHappened( if (regardStartAndEndAsSeparateAtomicActions) DurationalCodeFragmentEnded else AtomicCodeFragmentExecuted)
49 | if (n.hasSuccess) {
50 | succeeded
51 | }
52 | deactivate
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/taskprocessor/Processor.scala:
--------------------------------------------------------------------------------
1 | package subscript.example.taskprocessor.ssactors
2 | import subscript.file
3 |
4 | import akka.actor._
5 | import subscript.example.taskprocessor.Protocol._
6 |
7 | import subscript.Predef._
8 | import subscript.akka._
9 |
10 | /**
11 | * Receives tasks. Executes some job on data. Responds with success.
12 | * Maybe fails (on JVM fatal failure or ordinary exception) and stays silent.
13 | */
14 | class Processor[Df, Rf](processor: Df => Rf) extends SubScriptActor {
15 |
16 | var taskId : Long = -1
17 | var taskRequester: ActorRef = null
18 | var worker : Option[ActorRef] = None
19 |
20 |
21 | script..
22 | live = task success ...
23 |
24 | task = < sender ! ReceiptConfirmation(id); reset(Some(id)); process(data)>>
25 | /*
26 | task = r$({
27 | case Task(data: Df, id) =>
28 | sender ! ReceiptConfirmation(id)
29 | reset(Some(id))
30 | process(data)
31 | })
32 | */
33 |
34 | success = <
35 | taskRequester ! s
36 | reset(None)
37 | >>
38 | /*
39 | success = r$({
40 | case s @ Success(id, Some(data: Rf)) if id == taskId && worker.exists(_ == sender) =>
41 | taskRequester ! s
42 | reset(None)
43 | })
44 | */
45 |
46 |
47 | /**
48 | * This method controls state transmissions between `busy` and `idle`.
49 | */
50 | def reset(maybeId: Option[Long]) {
51 | // Set the internal state to its primeval condition
52 | taskId = -1
53 | taskRequester = null
54 | worker.foreach(context stop _) // Kill worker if it exists and processes (irrelevant) task
55 |
56 | // If there's a new task - set the state appropriately
57 | maybeId.foreach {id =>
58 | taskId = id
59 | taskRequester = sender
60 | }
61 | }
62 |
63 | /**
64 | * Spawns a worker and gives it a task to process.
65 | */
66 | def process(data: Df) {
67 | val task: () => Rf = () => processor(data)
68 | worker = Some(context actorOf Props(classOf[Worker[Rf]], task, taskId))
69 | }
70 |
71 | }
72 |
73 | /**
74 | * Does some actual job and responds with success.
75 | */
76 | class Worker[R](task: () => R, id: Long) extends Actor {
77 | context.parent ! Success[R](id, Some(task()))
78 | def receive = {case x => context.parent forward x}
79 | }
80 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/scala/scalaParser/ProjectTests.scala:
--------------------------------------------------------------------------------
1 | package scalaParser
2 |
3 | import org.parboiled2.ParseError
4 | import utest._
5 | import utest.framework.Test
6 | import utest.util.Tree
7 |
8 | import scala.util.{Failure, Success}
9 |
10 | object ProjectTests {//extends TestSuite{
11 |
12 | println("running")
13 | def tests = TestSuite{
14 | def checkFile(path: String) = UnitTests.check(io.Source.fromFile(path).mkString, tag = path)
15 | def checkDir(path: String, filter: String => Boolean = _ => false) = {
16 |
17 | def listFiles(s: java.io.File): Iterator[String] = {
18 | val (dirs, files) = s.listFiles().toIterator.partition(_.isDirectory)
19 | files.map(_.getPath) ++ dirs.flatMap(listFiles)
20 | }
21 | for{
22 | f <- listFiles(new java.io.File(path))
23 | if f.endsWith(".scala")
24 | if !filter(f)
25 | }{
26 | println("CHECKING " + f)
27 | checkFile(f)
28 | }
29 | }
30 | 'test - checkFile("src/test/resources/test.scala")
31 |
32 | 'scalaParser - checkDir("src", _.contains("src/test/resources/subscript"))
33 | 'scalaJs - checkDir("scala-js")
34 | 'scalaz - checkDir("scalaz")
35 | 'shapeless - checkDir("shapeless")
36 | 'akka - checkDir("akka")
37 | 'lift - {
38 | val blacklist = Seq(
39 | // octal literals are deprecated
40 | "framework/core/util/src/main/scala/net/liftweb/util/CombParserHelpers.scala"
41 | )
42 | checkDir("framework", f => blacklist.exists(f.contains))
43 | }
44 | 'play - checkDir("playframework", f => f.endsWith(".scala.html"))
45 | 'scala{
46 | // Things that we won't bother parsing, mainly because they use XML literals
47 | val blacklist = Seq(
48 | // Not real Scala files
49 | "dbuild-meta-json-gen.scala",
50 | "genprod.scala",
51 | "disabled", // don't bother parsing disabled tests
52 | "neg", // or neg tests
53 | "virtpatmat_exhaust_big.scala",
54 | "deprecate-early-type-defs.scala", // or deprecated tests
55 | // or unicode escapes
56 | "test/files/run/literals.scala",
57 | "test/files/run/t3835.scala",
58 | "test/files/run/richs.scala",
59 | // Lots of guys in these folders seem
60 | // to be borked, skip all of them
61 | "test/files/positions",
62 | "test/files/presentation",
63 | "test/pending"
64 | )
65 | checkDir("scala", f => blacklist.exists(f.contains))
66 |
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/ast/Ast.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.ast
2 |
3 |
4 | object Ast extends Ast
5 |
6 | trait Ast extends Core
7 | with Header
8 | with Operators
9 | with Terms
10 | with UtilNodes
11 | with CodePrimitives {
12 | import Constants._
13 |
14 | case class Literal(content: String) extends LiteralNode
15 |
16 | case class SubScriptCode(modifiers : Seq[String], scriptDefs: Seq[Node]) extends Node {
17 | def rewrite(implicit context: Context, output: Output) = {
18 | val dContext = context + (Key.MODIFIERS -> modifiers)
19 | scriptDefs.map(_.compile(dContext)).mkString("\n")
20 | }
21 | }
22 |
23 | case class ScriptDef(header: ScriptHeader, body: Option[Node]) extends Node {
24 | def rewrite(implicit context: Context, output: Output) = {
25 | val modifierList = context(Key.MODIFIERS).asInstanceOf[Seq[String]]
26 | val modifiers = {
27 | val mods = modifierList.mkString(" ")
28 | if (!mods.isEmpty) mods + " " else mods
29 | }
30 |
31 | val bodyStr = body.map {b =>
32 | val bodyCtx = context ++ Map(
33 | Key.HEADER_NAME -> header.name
34 | , Key.FORMAL_PARAMS -> header.args.flatten.map {
35 | case FormalConstrainedParameter(_, name, _, _) => Some(s"""$name.~??(Symbol("$name"))""")
36 | case FormalOutputParameter (_, name, _, _) => Some(s"""$name.~?(Symbol("$name"))""" )
37 | case _ => None
38 | }.filter(_.isDefined).map(_.get)
39 | )
40 |
41 | s""" = ${b.compile(bodyCtx, output)}"""
42 | }.getOrElse("")
43 |
44 | s"""${modifiers}def ${header.compile}$bodyStr"""
45 | }
46 | }
47 |
48 | case class ScriptBody(expr: Node) extends Node with AspectNode {
49 | val name = Key.SCRIPT
50 |
51 | def rewriteRaw(implicit context: Context, output: Output) = {
52 | val headerName = context(Key.HEADER_NAME ).asInstanceOf[String]
53 | val formalParams = context.get(Key.FORMAL_PARAMS).asInstanceOf[Option[Seq[String]]].map {params =>
54 | if (params.isEmpty) "" else s""", ${params.mkString(", ")}"""
55 | }.getOrElse("")
56 |
57 | s"""${DSL.Term.SCRIPT}[Any](None, Symbol("$headerName")$formalParams){(${Name.NODE}: ${DSL.Type.SCRIPT}[Any]) =>
58 | | implicit val ${Name.SCRIPT} = ${Name.NODE}
59 | |${expr.compile}}""".stripMargin
60 | }
61 | }
62 |
63 | def metaString(str: String) = '"' + str
64 | .replace("\\", "\\\\")
65 | .replace("\"", "\\\"")
66 | .replace("\n", "\\n" ) + '"'
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/framework/core/jvm/src/main/scala/subscript/vm/executor/CommonScriptExecutor.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.executor
2 |
3 | import scala.util.{Try}
4 | import subscript.vm._
5 | import subscript.vm.executor.data._
6 | import subscript.vm.executor.parts._
7 | import subscript.DSL._
8 | import scala.collection.mutable.Buffer
9 | import subscript.vm.executor.data.MessageHandlers.MessageHandler
10 | import subscript.vm.model.callgraph.ScriptResultHolder
11 |
12 |
13 | class CommonScriptExecutor[S] extends AbstractScriptExecutor[S] with Tracer with
14 | DefaultHandlers {
15 | var traceLevel = 0
16 |
17 | // the next statement is outcommented because the locking interferes with the synchronisation of the queue itself
18 | // the purpose was to notify this executor when an asynchronously executed code fragment had finished
19 | // so that this executor could wake up in case it had been waiting.
20 | // this notification is now only done in doCodeThatInsertsMsgs_synchronized
21 | //msgQueue addListener new MessageQueuedNotifier(this)
22 | msgHandlers sInsert defaultHandler
23 | msgHandlers sInsert communicationHandler
24 | msgHandlers sInsert continuationHandler
25 |
26 | def fail = () // needed because this is a ResultHolder; probably a different place for _fail would be better
27 |
28 | def run[R<:S](s: Script[R]) = {
29 | initializeExecution(s)
30 | while (hasActiveProcesses) {
31 | updateCollections()
32 | if (tryHandleMessage(Int.MinValue)==null) awaitMessages
33 | }
34 | trace(s"$this Exit main loop")
35 | $ = s.$
36 | this
37 | }
38 |
39 | def awaitMessages {
40 | trace(s"$this awaitMessages")
41 | messageAwaiting
42 | synchronized { // TBD: there should also be a synchronized call in the CodeExecutors
43 | if (msgQueue.collection.size == 0) { // looks stupid, but event may have happened¬ify() may have been called during tracing
44 | trace(s"$this wait - start")
45 | wait() // for an event to happen
46 | trace(s"$this wait - end")
47 | }
48 | }
49 | // note: there may also be deadlock because of unmatching communications
50 | // so there should preferably be a check for the existence of waiting event handling actions
51 | }
52 |
53 | /*
54 | * Execute the given code that may insert some call graph messages into the message queue.
55 | * This must be done in a synchronized way, and it may need to cause the call to wait()
56 | * in awaitMessages to end. Therefore this method does notify as well.
57 | */
58 | def doCodeThatInsertsMsgs_synchronized(code: =>Unit): Unit = synchronized{ code; trace(s"$this notify"); notify }
59 | }
60 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/main/scala/subscript/Predef.scala:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of Subscript - an extension of the Scala language
3 | with constructs from Process Algebra.
4 |
5 | Subscript is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License and the
7 | GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Subscript consists partly of a "virtual machine". This is a library;
12 | Subscript applications may distribute this library under the
13 | GNU Lesser General Public License, rather than under the
14 | GNU General Public License. This way your applications need not
15 | be made Open Source software, in case you don't want to.
16 |
17 | Subscript is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You may have received a copy of the GNU General Public License
23 | and the GNU Lesser General Public License along with Subscript.
24 | If not, see
25 | */
26 |
27 | package subscript
28 | import subscript.language
29 |
30 | import scala.util.{Try,Success,Failure}
31 |
32 | import subscript.vm._
33 | import subscript.DSL._
34 | import subscript.vm.executor._
35 | import subscript.vm.model.template._
36 | import subscript.vm.model.template.concrete._
37 | import subscript.vm.model.callgraph._
38 | import subscript.vm.model.callgraph.generic._
39 |
40 | import subscript.objectalgebra._
41 |
42 | // Predefined stuff - pass and some scripts: times, delta, epsilon, nu
43 | //
44 | object Predef extends CorePredefTrait {
45 |
46 | implicit script..
47 | process2script(p: SSProcess) = p.lifecycle
48 |
49 | script..
50 | times(n:Int) = while(pass
5 | import Constants.DSL.Type._
6 |
7 | case class ScriptHeader(name: String, args: Seq[Seq[Parameter]], implicitArgs: Option[Seq[Parameter]], tpe: Option[String]) extends Node {
8 | def rewrite(implicit context: Context, output: Output): String = {
9 | def compileArgs(args: Seq[Parameter]): String = args.map(_.compile).mkString(", ")
10 |
11 | val explicitArgsStr: String = args
12 | .map(compileArgs)
13 | .map {args => s"($args)"}
14 | .mkString
15 |
16 | val implicitArgsStr: String =
17 | implicitArgs.map {args => s"(implicit ${compileArgs(args)})"}.getOrElse("")
18 |
19 | val argsStr: String = explicitArgsStr + implicitArgsStr
20 |
21 | val tpeStr: String = tpe.map {t => s": $SCRIPT_NODE[$t]"}.getOrElse("")
22 |
23 | s"$name$argsStr$tpeStr"
24 | }
25 | }
26 |
27 | trait Parameter extends Node {
28 | val name : String
29 | val tpe : String
30 | val annots : String
31 | val defaultVal: Option[String]
32 |
33 |
34 | def tpeStr(transform: String => String): String = s": ${transform(tpe)}"
35 |
36 | def wrappedTpeStr(enclosingType: String) = tpeStr {t => s"$enclosingType[$t]"}
37 | def pureTpeStr = tpeStr(x => x)
38 |
39 | def annotsStr: String = if (!annots.isEmpty) annots + " " else ""
40 | def defaultValStr: String = defaultVal.map {v => s" = $v"}.getOrElse("")
41 | }
42 |
43 | case class NormalParameter(annots: String, name: String, tpe: String, defaultVal: Option[String]) extends Parameter {
44 | def rewrite(implicit context: Context, output: Output): String = s"$annotsStr$name$pureTpeStr$defaultValStr"
45 | }
46 |
47 | case class FormalOutputParameter(annots: String, name: String, tpe: String, defaultVal: Option[String]) extends Parameter {
48 | def rewrite(implicit context: Context, output: Output): String = s"$annotsStr$name${wrappedTpeStr(OUTPUT_PARAMETER)}$defaultValStr"
49 | }
50 |
51 | case class FormalConstrainedParameter(annots: String, name: String, tpe: String, defaultVal: Option[String]) extends Parameter {
52 | def rewrite(implicit context: Context, output: Output): String = s"$annotsStr$name${wrappedTpeStr(FORMAL_CONSTRAINED_PARAMETER)}$defaultValStr"
53 | }
54 |
55 | case class ConstrainableOutputParameter(annots: String, name: String, tpe: String, defaultVal: Option[String]) extends Parameter {
56 | def rewrite(implicit context: Context, output: Output): String = s"$annotsStr$name${wrappedTpeStr(CONSTRAINABLE_OUTPUT_PARAMETER)}$defaultValStr"
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/plugins/enhanced-macros/src/main/scala/subscript/enhancedmacros/Plugin.scala:
--------------------------------------------------------------------------------
1 | package subscript.enhancedmacros
2 |
3 | import scala.tools.nsc.Global
4 | import scala.tools.nsc.plugins.{Plugin => NscPlugin}
5 | import scala.reflect.internal.Mode
6 |
7 | class Plugin(val global: Global) extends NscPlugin {
8 |
9 | import global._
10 | import analyzer._
11 | import analyzer.{MacroPlugin => NscMacroPlugin}
12 |
13 | val name = "enhancedmacros"
14 | val description = "Enables whitebox macros to receive the type from their enclosing environment"
15 | val components = Nil
16 |
17 |
18 | class DefMacroExpanderEnhanced(typer: Typer, expandee: Tree, mode: Mode, outerPt: Type) extends DefMacroExpander(typer, expandee, mode, outerPt) {
19 | override def onSuccess(expanded0: Tree) = {
20 | // prematurely annotate the tree with a macro expansion attachment
21 | // so that adapt called indirectly by typer.typed knows that it needs to apply the existential fixup
22 | linkExpandeeAndExpanded(expandee, expanded0)
23 |
24 | def typecheck(label: String, tree: Tree, pt: Type): Tree = {
25 | if (tree.isErrorTyped) tree
26 | else {
27 | if (macroDebugVerbose) println(s"$label (against pt = $pt): $tree")
28 | // `macroExpandApply` is called from `adapt`, where implicit conversions are disabled
29 | // therefore we need to re-enable the conversions back temporarily
30 | val result = typer.context.withImplicitsEnabled(typer.typed(tree, mode, pt))
31 | if (result.isErrorTyped && macroDebugVerbose) println(s"$label has failed: ${typer.context.reporter.errors}")
32 | result
33 | }
34 | }
35 |
36 | if (isBlackbox(expandee)) {
37 | val expanded1 = atPos(enclosingMacroPosition.makeTransparent)(Typed(expanded0, TypeTree(innerPt)))
38 | typecheck("blackbox typecheck", expanded1, outerPt)
39 | } else {
40 | // We are now vulnurable to SI-6992, SI-8048 and SI-8209
41 | // Though it is not likely that they will happen in our application context
42 | val expanded1 = typecheck("whitebox typecheck #1", expanded0, outerPt)
43 | typecheck("whitebox typecheck #2", expanded1, innerPt)
44 | }
45 | }
46 | }
47 |
48 | object MacroPlugin extends NscMacroPlugin {
49 |
50 | override def pluginsMacroExpand(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Option[Tree] = {
51 | expandee match {
52 | case q"subscript.DSL._maybeVarCall($_)" =>
53 | val expander = new DefMacroExpanderEnhanced(typer, expandee, mode, pt)
54 | Some(expander(expandee))
55 |
56 | case _ => None
57 | }
58 | }
59 |
60 | }
61 |
62 | analyzer.addMacroPlugin(MacroPlugin)
63 | }
64 |
--------------------------------------------------------------------------------
/framework/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val commonSettings = Seq(
2 | organization := "org.subscript-lang"
3 | , version := "3.0.5-SNAPSHOT"
4 |
5 | , publishTo := {
6 | if (isSnapshot.value)
7 | Some("snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/")
8 | else
9 | Some("releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2")
10 | }
11 |
12 | , scalaVersion := "2.11.7"
13 |
14 | , pomExtra :=
15 | https://github.com/scala-subscript/subscript
16 |
17 |
18 | GNU LGPL
19 | http://www.gnu.org/licenses/lgpl-3.0.en.html
20 | repo
21 |
22 |
23 |
24 | git://github.com/scala-subscript/subscript.git
25 | scm:git://github.com/scala-subscript/subscript.git
26 |
27 |
28 |
29 | Andre van Delft
30 | https://github.com/AndreVanDelft
31 |
32 |
33 | anatoliykmetyuk
34 | Anatoliy Kmetyuk
35 | https://github.com/anatoliykmetyuk
36 |
37 |
38 | ) ++ SubscriptSbt.projectSettings
39 |
40 | lazy val root = (project in file("."))
41 | .aggregate(coreJVM, coreJS, akka, swing, corescripts)
42 | .settings(
43 | packagedArtifacts := Map.empty // Don't publish root to maven
44 | )
45 |
46 | lazy val core = (crossProject in file("core"))
47 | .settings(commonSettings)
48 | .settings(
49 | name := "subscript-core"
50 | , libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.7"
51 | // , excludeFilter in (Test, unmanagedSources) := "*.scala"
52 | )
53 |
54 | lazy val coreJVM = core.jvm
55 | lazy val coreJS = core.js
56 |
57 | lazy val akka = (project in file("akka"))
58 | .dependsOn(coreJVM, corescripts)
59 | .settings(commonSettings)
60 | .settings(
61 | name := "subscript-akka"
62 | , libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.3.11"
63 | )
64 |
65 | lazy val swing = (project in file("swing"))
66 | .dependsOn(coreJVM, corescripts)
67 | .settings(commonSettings)
68 | .settings(
69 | name := "subscript-swing"
70 | , libraryDependencies += "org.scala-lang" % "scala-swing" % "2.11.0-M7"
71 | , excludeFilter in Compile := "Scripts.scala" | "SubScriptDebugger.scala"
72 | )
73 |
74 | lazy val corescripts = (project in file("core-scripts"))
75 | .dependsOn(coreJVM)
76 | .settings(commonSettings)
77 | .settings(
78 | name := "subscript-core-scripts"
79 | , libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.4" % "test"
80 | )
81 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/test/scala/subscript/SubScriptSuite.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | import scala.util._
4 |
5 | import subscript.language
6 | import subscript.Predef._
7 |
8 | import org.scalatest._
9 |
10 | class SubScriptSuite extends FlatSpec with Matchers
11 | with CommonHelpers {
12 |
13 | "Constructor calls" should "be possible without parenthesis" in {
14 | class Foo extends subscript.objectalgebra.SSProcess {
15 | override script live = [+]
16 | }
17 |
18 | ([new Foo ^new Foo new Foo]).e shouldBe a [Success[_]]
19 | }
20 |
21 | "Variables" should "be defineable in terms of other variables" in {
22 | [
23 | var x = 1
24 | var y = x + 1
25 | ^y
26 | ].e shouldBe Success(2)
27 | }
28 |
29 | it should "be defineable via blocks containing other variables (issue #5)" in {
30 | [
31 | val a = {
32 | val x = 3
33 | x
34 | }
35 | ^a
36 | ].e shouldBe Success(3)
37 | }
38 |
39 | "Script calls" should "be extracted from local vars" in {
40 | var flag = false
41 | case class Foo(x: Int) {
42 | def bar: Unit = flag = true
43 | }
44 |
45 | ([
46 | var foo = Foo(3)
47 | foo.bar
48 | ]).e
49 |
50 | flag shouldBe true
51 | }
52 |
53 | "Output params" should "be usable from a script" in {
54 | implicit script param2script(?x: Int) = let x = 10
55 |
56 | script foo =
57 | var bar = 3
58 | ?bar
59 | ^bar
60 |
61 | foo.e shouldBe Success(10)
62 | }
63 |
64 | "Constrained params" should "work" in {
65 | implicit script param2script(??x: Int) = let x = 10
66 |
67 | script foo =
68 | var bar = 3
69 | ?bar ?if (bar > 0)
70 | ^bar
71 |
72 | foo.e shouldBe Success(10)
73 | }
74 |
75 | "Adapting params" should "work" in {
76 | implicit script param2script(??x: Int) = let x = 10
77 |
78 | script..
79 | f(??x: Int) = ??x
80 | foo =
81 | var bar = 3
82 | f(?bar)
83 | ^bar
84 |
85 | foo.e shouldBe Success(10)
86 | }
87 |
88 | "Do construct" should "work for normal code" in {
89 | ([
90 | var foo = 3
91 | do! foo += 1
92 | ^foo
93 | ]).e shouldBe Success(4)
94 | }
95 |
96 | it should "work for threaded code" in {
97 | ([
98 | var foo = 3
99 | do* foo += 1
100 | ^foo
101 | ]).e shouldBe Success(4)
102 | }
103 |
104 | "Call graph nodes' parameters" should "work" in {
105 | ([
106 | do! here.n_ary_op_ancestor.setProperty("FOO", 1)
107 | {!here.n_ary_op_ancestor.getProperty[String, Int]("FOO")!}^
108 | ]).e shouldBe Success(Some(1))
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/framework/core/js/src/main/scala/subscript/vm/executor/CommonScriptExecutor.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.executor
2 |
3 | import scala.util.{Try}
4 | import subscript.vm._
5 | import subscript.vm.executor.data._
6 | import subscript.vm.executor.parts._
7 | import subscript.DSL._
8 | import scala.collection.mutable.Buffer
9 | import subscript.vm.executor.data.MessageHandlers.MessageHandler
10 | import subscript.vm.model.callgraph.ScriptResultHolder
11 |
12 |
13 | class CommonScriptExecutor[S] extends AbstractScriptExecutor[S] with Tracer with
14 | DefaultHandlers {
15 | var traceLevel = 0
16 |
17 | // the next statement is outcommented because the locking interferes with the synchronisation of the queue itself
18 | // the purpose was to notify this executor when an asynchronously executed code fragment had finished
19 | // so that this executor could wake up in case it had been waiting.
20 | // this notification is now only done in doCodeThatInsertsMsgs_synchronized
21 | //msgQueue addListener new MessageQueuedNotifier(this)
22 | msgHandlers sInsert defaultHandler
23 | msgHandlers sInsert communicationHandler
24 | msgHandlers sInsert continuationHandler
25 |
26 | def fail = () // needed because this is a ResultHolder; probably a different place for _fail would be better
27 |
28 | def run[R<:S](s: Script[R]) = {
29 | initializeExecution(s)
30 | messageLoop()
31 | trace(s"$this Exit main loop. hasActiveProcesses = $hasActiveProcesses")
32 | $ = s.$
33 | this
34 | }
35 |
36 | def messageLoop(): Unit = while (hasActiveProcesses) {
37 | updateCollections()
38 | if (tryHandleMessage(Int.MinValue)==null) { awaitMessages; return }
39 | }
40 |
41 | def awaitMessages {
42 | trace(s"$this awaitMessages")
43 | messageAwaiting
44 | if (msgQueue.collection.size == 0) { // looks stupid, but event may have happened¬ify() may have been called during tracing
45 | trace(s"$this wait - start")
46 | startWaitingForMessages()
47 | }
48 | // note: there may also be deadlock because of unmatching communications
49 | // so there should preferably be a check for the existence of waiting event handling actions
50 | }
51 |
52 | var waiting = false
53 |
54 | def startWaitingForMessages(): Unit = {
55 | waiting = true
56 | }
57 |
58 | def endWaitingForMessages(): Unit = {
59 | waiting = false
60 | trace(s"$this wait - end")
61 | messageLoop()
62 | }
63 |
64 | /*
65 | * Execute the given code that may insert some call graph messages into the message queue.
66 | * This must be done in a synchronized way, and it may need to cause the call to wait()
67 | * in awaitMessages to end. Therefore this method does notify as well.
68 | */
69 | def doCodeThatInsertsMsgs_synchronized(code: =>Unit): Unit = { code; trace(s"$this notify"); if (waiting) endWaitingForMessages }
70 | }
71 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/core/Test_rewritten.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 | import subscript.file
3 |
4 | // import org.junit.runner.RunWith
5 |
6 | import subscript.Predef._
7 | import subscript.DSL._
8 | import subscript.vm.{N_code_unsure, SimpleScriptDebugger, Script}
9 | import subscript.vm.model.callgraph._
10 | import subscript.vm.executor._
11 |
12 | class TestC {
13 |
14 | def times(n: Int) = subscript.DSL._script[Any](None, Symbol("times")){(_node: subscript.vm.Script[Any]) =>
15 | implicit val script = _node
16 | subscript.DSL._while (_node => {
17 | implicit val here = _node
18 | subscript.DSL._maybeVarCall("here.pass < n")
19 | })}
20 | def key(c: subscript.vm.FormalConstrainedParameter[Char]) = subscript.DSL._script[Any](None, Symbol("key"), c.~??(Symbol("c"))){(_node: subscript.vm.Script[Any]) =>
21 | implicit val script = _node
22 | subscript.DSL._normal[Any] (_node => {
23 | implicit val here = _node
24 | subscript.DSL._maybeVarCall("subscript.DSL._maybeVarAssignment(\"c\",subscript.DSL._maybeVarCall(\"'!'\"))")
25 | }, true)}
26 | def mainScript(args: Array[String]) = {
27 | val c = subscript.DSL._declare[Char](scala.Symbol("c"))
28 | subscript.DSL._script[Any](None, Symbol("mainScript")){(_node: subscript.vm.Script[Any]) =>
29 | implicit val script = _node
30 | subscript.DSL._seq(subscript.DSL._val(c, (_node: subscript.vm.N_localvar[Char]) => {implicit val here = _node; val tr: Char = subscript.DSL._maybeVarCall("' '"); tr}), subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => key(subscript.DSL._maybeVarCall("subscript.DSL._actualOutputParameter(\"c\")"))), subscript.DSL._normal[Any] (_node => {
31 | implicit val here = _node
32 | subscript.DSL._maybeVarCall("println(subscript.DSL._maybeVarCall(\"s\\\"key => $c\\\"\"))")
33 | }, true)), subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => key(subscript.DSL._maybeVarCall("'!'"))), subscript.DSL._normal[Any] (_node => {
34 | implicit val here = _node
35 | subscript.DSL._maybeVarCall("println(subscript.DSL._maybeVarCall(\"\\\"key <= '!'\\\"\"))")
36 | }, true)))}
37 |
38 | }
39 |
40 | val times1: Int=>Script[Any] = n=>{_script(this, 'lambda) {script => _while{implicit here=>passScript[Any] = n=>subscript.DSL._script[Any](None, Symbol("lambda")){(_node: subscript.vm.Script[Any]) =>
42 | implicit val script = _node
43 | subscript.DSL._while (_node => {
44 | implicit val here = _node
45 | subscript.DSL._maybeVarCall("here.pass < n")
46 | })}
47 | //val times3: Int=>Script = [ while(pass < _) ]
48 | //val noXml = [noXML]
49 |
50 | //TBD: allow ? in all parameter lists; parse < script > blocks
51 | }
52 | object Test extends TestC {
53 | // bridge method:
54 | def main( args: Array[String]): Unit = _execute(mainScript(args))
55 | }
56 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/Switches.scala:
--------------------------------------------------------------------------------
1 | package scalaParser
2 |
3 | import org.parboiled2._
4 |
5 | /**
6 | * Some rules may be different depending on the context.
7 | * For example, Id must be wrapped in the _maybeVarCall macro
8 | * if in Script block context, and must be left as is otherwise.
9 | * Switches are object that store information about the current context.
10 | * Based on the state of a certain switch, rules may decide what
11 | * fors they should take.
12 | */
13 | trait Switch {
14 | val DEFAULT = 0
15 | var state = DEFAULT
16 | }
17 |
18 | /**
19 | * RuleBank stores all possible rule variations with the states
20 | * under which these variations take palce.
21 | */
22 | abstract class RuleBank[+T](val switch: Switch) {
23 |
24 | implicit def int2rule(x: Int): () => Rule1[T] = () => ruleMap(x).apply()
25 |
26 | def default = switch.DEFAULT
27 |
28 | def ruleMap: Map[Int, () => Rule1[T]]
29 |
30 | def apply(): () => Rule1[T] = ruleMap.withDefault(_ => ruleMap(default))(switch.state)
31 |
32 | }
33 |
34 | trait Switches {this: Metarules =>
35 |
36 | object ScopeSwitch extends Switch {
37 | val NORMAL = DEFAULT
38 | val SCRIPT = 1
39 | val NORMAL_IN_SCRIPT = 2
40 |
41 | val PARENTHESES = 3
42 | val LAUNCH_ANCHOR = 4
43 | val LAUNCH = 5
44 |
45 | val ASSIGNMENT = 6
46 | val PATTERN = 7
47 |
48 | val NICE_SCRIPT_CALL = 8
49 | }
50 |
51 | abstract class ScopeBank[+T] extends RuleBank[T](ScopeSwitch)
52 |
53 | def WithScope[T](rle: () => Rule1[T], scope: Int): Rule1[T] = {
54 | var previousState = -1
55 | def reset = ScopeSwitch.state = previousState
56 |
57 | Try(
58 | before = {previousState = ScopeSwitch.state; ScopeSwitch.state = scope}
59 | , rle = rle
60 | , after = reset
61 | , rollback = reset
62 | )
63 | }
64 |
65 | import ScopeSwitch._
66 | def WithNormal [T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, NORMAL )
67 | def WithScript [T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, SCRIPT )
68 | def WithNormalInScript[T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, NORMAL_IN_SCRIPT)
69 | def WithParentheses [T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, PARENTHESES )
70 | def WithLaunchAnchor [T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, LAUNCH_ANCHOR )
71 | def WithLaunch [T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, LAUNCH )
72 | def WithAssignment [T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, ASSIGNMENT )
73 | def WithPattern [T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, PATTERN )
74 | def WithNiceScriptCall[T](rle: () => Rule1[T]): Rule1[T] = WithScope(rle, NICE_SCRIPT_CALL)
75 |
76 | }
77 |
78 | trait Settings {
79 | val settings: Seq[String]
80 | }
81 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/parser/Header.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript.parser
2 |
3 | import language.implicitConversions
4 | import org.parboiled2._
5 | import scalaParser._
6 | import scalaParser.syntax._
7 |
8 | import scalaParser.subscript.ast.Ast
9 |
10 |
11 | trait Header {this: SubScript with Exprs =>
12 |
13 | def ScriptHeader: R[Ast.ScriptHeader] = {
14 | def AnnotBlahBlah: R1 = rule( Annot.* ~> ConcatSeqNoDelim ~ TypeArg ~> Concat )
15 | def FunTypeArgs : R1 = rule( '[' ~ OneOrMore(() => AnnotBlahBlah, () => ',') ~ ']' ~> Concat3 )
16 |
17 | def FunAllArgs: R[(Seq[Seq[Ast.Parameter]], Option[Seq[Ast.Parameter]])] = {
18 | def Trans1: (String, String, String, Seq[Ast.Parameter], String) => Seq[Ast.Parameter] =
19 | (_, _, _, args, _) => args
20 |
21 | def Trans2: (Seq[Seq[Ast.Parameter]], Option[Seq[Ast.Parameter]]) => (Seq[Seq[Ast.Parameter]], Option[Seq[Ast.Parameter]]) = // Create a pair
22 | (a, b) => (a, b)
23 |
24 | rule( FunArgs.* ~ (OneNLMax ~ '(' ~ `implicit` ~ Args ~ ')' ~> Trans1).? ~> Trans2 )
25 | }
26 |
27 | def FunArgs: R[Seq[Ast.Parameter]] = {
28 | def Trans1: (String, String, Option[Seq[Ast.Parameter]], String) => Seq[Ast.Parameter] = (_, _, args, _) => args.getOrElse(Nil)
29 | rule( OneNLMax ~ '(' ~ Args.? ~ ')' ~> Trans1 )
30 | }
31 |
32 | def Args: R[Seq[Ast.Parameter]] = {
33 | def FunArgGen[A <: Ast.Parameter](id: () => R1, argFun: (String, String, String, Option[String]) => A): R[A] = rule {
34 | Annot.* ~> ConcatSeqNoDelim ~ id() ~ (`:` ~ Spaces(() => ParamType) ~> SecondStr) ~ (`=` ~ Spaces(() => TypeExpr) ~> SecondStr).? ~> argFun
35 | }
36 |
37 | def QId: R1 = rule { WSR0 ~ '?' ~ Id ~> SecondStr }
38 | def QQId: R1 = rule { WSR0 ~ "??" ~ Id ~> SecondStr }
39 |
40 | def NormalParameter : R[Ast.NormalParameter ] = FunArgGen(() => IdS, Ast. NormalParameter)
41 | def FormalOutputParameter : R[Ast.FormalOutputParameter ] = FunArgGen(() => QId , Ast. FormalOutputParameter)
42 | def FormalConstrainedParameter: R[Ast.FormalConstrainedParameter] = FunArgGen(() => QQId , Ast.FormalConstrainedParameter)
43 |
44 | def FunArg: R[Ast.Parameter] = rule (
45 | FormalConstrainedParameter
46 | | FormalOutputParameter
47 | | NormalParameter
48 | )
49 |
50 | rule( FunArg + ',' )
51 | }
52 |
53 |
54 | rule( (!SSKeyword ~ Id ~ (FunTypeArgs.? ~> ExtractOpt) ~> Concat) ~ FunAllArgs ~ (`:` ~ Spaces(() => Type) ~> SecondStr).? ~>
55 | {(id: String, args: (Seq[Seq[Ast.Parameter]], Option[Seq[Ast.Parameter]]), tpe: Option[String]) => // Seq[Seq[Arg]] - ordinary Parameters; Option[Seq[Arg]] - implicit Parameters
56 | val (explicits, implicits) = args
57 | Ast.ScriptHeader(id, explicits, implicits, tpe)
58 | }
59 | )
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/lookupframe-example/LookupFrame.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import scala.language.implicitConversions
5 |
6 | import scala.swing._
7 | import scala.swing.event._
8 |
9 | import subscript.swing.SimpleSubscriptApplication
10 | import subscript.swing.Scripts._
11 |
12 | // Subscript sample application: a text entry field with a search button, that simulates the invocation of a background search
13 | //
14 | // Note: the main part of this source file has been manually compiled from Subscript code into plain Scala
15 |
16 | object LookupFrame extends LookupFrameApplication
17 |
18 | class LookupFrameApplication extends SimpleSubscriptApplication {
19 |
20 | val outputTA = new TextArea {editable = false}
21 | val searchButton = new Button("Go") {enabled = false}
22 | val searchLabel = new Label("Search") {preferredSize = new Dimension(45,26)}
23 | val searchTF = new TextField {preferredSize = new Dimension(100, 26)}
24 |
25 | val top = new MainFrame {
26 | title = "LookupFrame - Subscript"
27 | location = new Point (100,100)
28 | preferredSize = new Dimension(300,300)
29 | contents = new BorderPanel {
30 | add(new FlowPanel(searchLabel, searchTF, searchButton), BorderPanel.Position.North)
31 | add(outputTA, BorderPanel.Position.Center)
32 | }
33 | }
34 | override def live = subscript.DSL._execute(liveScript)
35 |
36 | override script liveScript = ... searchSequence
37 |
38 | def sleep(time: Long) = Thread.sleep(time)
39 | script..
40 | searchSequence = searchCommand showSearchingText searchInDatabase showSearchResults
41 | searchCommand = searchButton
42 | showSearchingText = @gui: {outputTA.text = "Searching: "+searchTF.text}
43 | showSearchResults = @gui: {outputTA.text = "Found: "+here.index+" items"}
44 | searchInDatabase = {* sleep(2000) *} // simulate a time consuming action
45 |
46 | implicit script vkey(??k: Key.Value) = vkey2(top, ??k)
47 |
48 | /* translated into:
49 |
50 | override def _live = _script(this, 'live ) {_seq(_loop, _searchSequence)}
51 | def _searchSequence = _script(this, 'searchSequence ) {_seq(_searchCommand, _showSearchingText, _searchInDatabase, _showSearchResults)}
52 | def _searchCommand = _script(this, 'searchCommand ) {_clicked(searchButton)}
53 | def _showSearchingText = _script(this, 'showSearchingText) {_at{gui0} (_normal0 { outputTA.text = "Searching: "+searchTF.text})}
54 | def _showSearchResults = _script(this, 'showSearchResults) {_at{gui0} (_normal{(here: N_code_normal) => outputTA.text = "Found: "+here.index+" items"})}
55 | def _searchInDatabase = _script(this, 'searchInDatabase ) {_threaded0{Thread.sleep(2000)}}
56 |
57 | // bridge method
58 | override def live = _execute(_live )
59 | *
60 | */
61 | }
62 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/concrete/Roots.scala:
--------------------------------------------------------------------------------
1 | // package subscript.vm.model.callgraph.concrete
2 | package subscript.vm
3 |
4 | import subscript.vm.executor._
5 | import subscript.vm.model.callgraph._
6 | import subscript.vm.model.callgraph.generic._
7 | import subscript.vm.model.template.concrete._
8 | import subscript.DSL._
9 | import subscript.vm.model.template.TemplateNode
10 |
11 | // Local launches and calls
12 | case class N_launch(template: T_launch)
13 | extends CallGraphLeafNode
14 | {type T = T_launch}
15 |
16 | case class N_launch_anchor(template: T_launch_anchor)
17 | extends CallGraphTreeNode
18 | with ChildrenState // Make it extend this just because of extendedInfoString???
19 | {
20 | type T = T_launch_anchor
21 | override def infoString = extendedInfoString
22 | override def removeParent(p: Parent) {if (p!=null) super.removeParent(p)}
23 | }
24 |
25 | case class N_call[R](template: T_call[R]) extends CallGraphTreeNode with ScriptResultHolder[R] {
26 | type T = T_call[R]
27 | var t_callee: T_script = null
28 | def callee = children.head.asInstanceOf[Script[R]]
29 | def mustPropagateResultValue = template.mustPropagateResultValue
30 | def fail: Unit = {} // Required by ScriptResultHolder. TBD: cleanup
31 |
32 | //var t_commcallee: T_commscript = null
33 |
34 | //def communicator: Communicator = if (t_commcallee==null) null else t_commcallee.communicator
35 | def stopPending {}//if (communicator!=null) {communicator.removePendingCall(this)}} // stop pending unmatched communication partners
36 | var actualParameters: scala.collection.immutable.Seq[ActualParameter[_<:Any]] = Nil
37 | def calls(t: T_script, args: FormalParameter[_]*): Unit = {
38 | this.actualParameters = args.toList.map(_.asInstanceOf[ActualParameter[_]])
39 | this.t_callee = t
40 | }
41 | //def calls(t: T_commscript, args: FormalParameter[_]*): Unit = {
42 | // this.actualParameters = args.toList.map(_.asInstanceOf[ActualParameter[_]])
43 | // this.t_commcallee = t
44 | //}
45 | def allActualParametersMatch: Boolean = actualParameters.forall {_.matches}
46 | def transferParameters : Unit = actualParameters.foreach{_.transfer}
47 | }
48 |
49 | trait ScriptTrait[R] extends ScriptResultHolder[R]
50 |
51 | // Root script types
52 | /*
53 | * Note: maybe this should become a CallGraphNode, since it may not have a unique parent.
54 | * There is quite some code that assumes all nodes have such a unique parent, so this change would not be easy
55 | */
56 | case class Script[R](template: T_script, p: FormalParameter[_]*)
57 | extends CallGraphTreeNode with ScriptTrait[R] {
58 | type T = T_script
59 | def fail: Unit = {} // Required by ScriptResultHolder. TBD: cleanup
60 | }
61 |
62 | //case class N_communication(var template: T_communication) extends CallGraphNode {
63 | // type T = T_communication
64 | //
65 | // var communication: Communication = null
66 | //
67 | // def inits(t: T_communication, owner: Any): TemplateNode = null // TBD
68 | // def _getParameter[T](p: Symbol): CommunicationParameter[T] = CommunicationParameter[T](p)
69 | //}
70 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/taskprocessor/Proxy.scala:
--------------------------------------------------------------------------------
1 | package subscript.example.taskprocessor.ssactors
2 | import subscript.file
3 |
4 | import akka.actor._
5 | import scala.concurrent.duration._
6 | import scala.concurrent.ExecutionContext.Implicits.global
7 | import scala.language.postfixOps
8 | import subscript.example.taskprocessor.Protocol
9 | import Protocol._
10 | import subscript.akka._
11 | import subscript.Predef._
12 |
13 | /**
14 | * The job of this actor is to provide improved guarantees on message
15 | * delivery.
16 | * It will make sure that there were at least maxRetries attempts to deliver message,
17 | * then it will wait for successful response for `timeout`. If Success is received,
18 | * it will be redirected to parent, otherwise Failure will be sent to parent.
19 | */
20 | class Proxy(
21 | target : ActorRef,
22 | maxRetries : Int,
23 | retryInterval: FiniteDuration,
24 | timeout : FiniteDuration
25 | ) extends SubScriptActor {
26 |
27 | var taskId : Long = -1
28 | var taskRequester : ActorRef = null
29 | var currentMessage: AnyRef = null
30 |
31 | def sleepFd(t: FiniteDuration) = Thread sleep t.toMillis
32 |
33 | script..
34 | //live = handle_task ; spam / receive_confirmation ; sleep(timeout) fail / handle_success ; ...
35 |
36 | times(x: Int) = while(here.pass reset(Some(id)); currentMessage = t>>
50 | /*
51 | handle_task = r$({
52 | case t @ Task(data, id) =>
53 | reset(Some(id))
54 | currentMessage = t
55 | })
56 | */
57 |
58 | receive_confirmation = <>
59 | // receive_confirmation = r$({case s @ ReceiptConfirmation(id) if id == taskId && sender == target =>})
60 |
61 | handle_success = < taskRequester ! s; reset(None)>>
62 | /*
63 | handle_success = r$({
64 | case s @ Success(id, Some(data)) if id == taskId =>
65 | taskRequester ! s
66 | reset(None)
67 | })
68 | */
69 | /**
70 | * In its first half, this method resets the state of the actor to
71 | * its primeval condition - stop all processing.
72 | * If the argument passed is not None, we start new processing (at least
73 | * reflect that it started in the internal state).
74 | */
75 | def reset(tid: Option[Long]) {
76 | // Stop all processing
77 | taskId = -1
78 | taskRequester = null
79 | currentMessage = null
80 |
81 | // Start new processing (at least document it)
82 | tid.foreach {id =>
83 | taskId = id
84 | taskRequester = sender
85 | }
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/scala/scalaParser/subscript/MarkerSuite.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript
2 |
3 | import scala.util._
4 |
5 | import org.parboiled2._
6 | import utest._
7 |
8 | import scalaParser.Scala
9 | import scalaParser.subscript.ast.{Ast, Constants}
10 |
11 | object MarkerSuite extends TestSuite with Checkers with Symbols {def tests = TestSuite {'subscript {
12 |
13 | * - marker(false)(
14 | s"""package torimatomeru
15 | |
16 | |package lols
17 | """.stripMargin
18 | )
19 | * - marker(true)(
20 | s"""package torimatomeru
21 | |import a
22 | |import ${Constants.Name.FILE}
23 | |import b
24 | """.stripMargin
25 | )
26 | * - marker(false)(
27 | s"""
28 | |package torimatomeru
29 | |
30 | |import org.parboiled2.ParseError
31 | |import utest._
32 | |import utest.framework.Test
33 | |import utest.util.Tree
34 | |
35 | |import scala.util.{Failure, Success}
36 | |
37 | |object SyntaxTest extends TestSuite
38 | """.stripMargin
39 | )
40 |
41 | // This one has 2 spaces after the import
42 | * - marker(true)(
43 | s"""
44 | |import ${Constants.Name.FILE}
45 | |object SyntaxTest extends TestSuite{
46 | | def marker[T](input: String) = {
47 | |
48 | | }
49 | |}
50 | """.stripMargin
51 | )
52 | * - marker(false)(
53 | s"""
54 | |object SyntaxTest{
55 | | a()
56 | | throw 1
57 | |}
58 | """.stripMargin
59 | )
60 | * - marker(false)(
61 | s"""
62 | |object SyntaxTest extends TestSuite{
63 | | {
64 | | println
65 | | throw 1
66 | | }
67 | |}
68 | """.stripMargin
69 | )
70 | * - marker(true)(
71 | s"""package scalatex
72 | |
73 | |
74 | |import org.parboiled2._
75 | |import torimatomeru.ScalaSyntax
76 | |
77 | |import scalatex.stages.{Trim, Parser, Ast}
78 | |import scalatex.stages.Ast.Block.{IfElse, For, Text}
79 | |import Ast.Chain.Args
80 | |
81 | |import ${Constants.Name.FILE}
82 | |
83 | |object ParserTests extends utest.TestSuite{
84 | | import Ast._
85 | | import utest._
86 | | def marker[T](input: String, parse: Parser => scala.util.Try[T], expected: T) = {
87 | | val parsed = parse(new Parser(input)).get
88 | | assert(parsed == expected)
89 | | }
90 | | def tests = TestSuite{}
91 | |}
92 | """.stripMargin
93 | )
94 | * - marker(false)(
95 | s"""
96 | |object Moo{
97 | | a
98 | | .b
99 | |
100 | | c
101 | |}
102 | """.stripMargin
103 | )
104 | * - marker(false)(
105 | s"""
106 | |object Moo{
107 | | filename
108 | | .asInstanceOf[Literal]
109 | |10
110 | |}
111 | """.stripMargin
112 | )
113 | * - marker(true)(
114 | s"""
115 | |import ${Constants.Name.FILE}
116 | |object Cow{
117 | | ().mkString
118 | |
119 | | 1
120 | |}
121 | """.stripMargin
122 | )
123 | }}}
124 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/vm/model/callgraph/generic/OptionalChildrenState.scala:
--------------------------------------------------------------------------------
1 | package subscript.vm.model.callgraph.generic
2 |
3 | import subscript.vm.executor._
4 | import subscript.vm.model.callgraph._
5 | import subscript.DSL._
6 |
7 | trait OptionalChildrenState extends ChildrenState {this: CallGraphNode =>
8 | /*
9 | * some bookkeeping.
10 | * Optional children are children of this operator (which must be parallel or similar),
11 | * which have been activated after an optional break had occurred, and for which no atomic action has happened.
12 | * This will in general happen in the "y" parts (and thereafter the "z" part) of
13 | * x & . & y
14 | * x & . & y & . & z
15 | */
16 | var aaHappenedInOptionalChildren = false
17 | var nActivatedOptionalChildren = 0
18 | var nActivatedOptionalChildrenWithSuccess = 0
19 | def nActivatedOptionalChildrenWithoutSuccess = nActivatedOptionalChildren - nActivatedOptionalChildrenWithSuccess
20 | def nActivatedMandatoryChildren = nActivatedChildren - nActivatedOptionalChildren
21 | def nActivatedMandatoryChildrenWithSuccess = nActivatedChildrenWithSuccess - nActivatedOptionalChildrenWithSuccess
22 | def nActivatedMandatoryChildrenWithoutSuccess = nActivatedChildrenWithoutSuccess - nActivatedOptionalChildrenWithoutSuccess
23 |
24 | /*
25 | * Consider
26 | * x & . & y and
27 | * x & . & y . & z
28 | * After activation of x, the activation is paused at the first period (".") in case atomic actions had been activated in x.
29 | * The pause is then undone, and y is activated as an optional part.
30 | * The position in the call graph of the period between x and y is then identified by indexChild_marksOptionalPart
31 | * If after activation of y another period is encountered and atomic actions had been activated in y,
32 | * then the position of that period is identified by indexChild_marksPause, and activation stops there.
33 | * If no atomic actions had been activated then activation just continues (maybe not a good strategy).
34 | *
35 | * As soon as such an atomic action has happened, the z part is activated, and
36 | * indexChild_marksOptionalPart becomes indexChild_marksPause, and the latter becomes -1.
37 | */
38 | var _indexChild_optionalBreak_secondLast = -1
39 | var _indexChild_optionalBreak_last = -1
40 | def indexChild_optionalBreak_secondLast = _indexChild_optionalBreak_secondLast
41 | def indexChild_optionalBreak_last = _indexChild_optionalBreak_last
42 | def indexChild_optionalBreak_last_=(v:Int) = {
43 | _indexChild_optionalBreak_secondLast = _indexChild_optionalBreak_last
44 | _indexChild_optionalBreak_last = v
45 | aaActivated_notBeforeLastOptionalBreak = false // reset for next time
46 | aaHappenedInOptionalChildren = false
47 | }
48 |
49 | var aaActivated_notBeforeLastOptionalBreak = false
50 | //var aaActivated_optional = false
51 |
52 | def aaHappened_resetNActivatedOptionalChildren = {
53 | aaHappenedInOptionalChildren = true
54 | nActivatedOptionalChildren = 0
55 | nActivatedOptionalChildrenWithSuccess = 0
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/ab-example/AB_rewritten.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import scala.swing._
5 | import scala.swing.event._
6 |
7 | import subscript.DSL._
8 |
9 | import subscript.swing.SimpleSubscriptApplication
10 | import subscript.swing.Scripts._
11 |
12 |
13 | // Subscript sample application: A..B
14 | //
15 | // Note: the main part of this source file has been manually compiled from Subscript code into plain Scala
16 |
17 |
18 | abstract class ABApplication extends SimpleSubscriptApplication {
19 | import scala.language.implicitConversions
20 |
21 | def getTitle: String
22 |
23 | val A = new Button("A") {enabled = false}
24 | val B = new Button("B") {enabled = false}
25 | val X = new Button("Exit") {enabled = false}
26 | val ABLabel = new Label("..A;B") {preferredSize = new Dimension(45,26)}
27 | val outputTA = new TextArea {editable = false}
28 |
29 | val top = new MainFrame {
30 | title = getTitle
31 | location = new Point (0,0)
32 | preferredSize = new Dimension(300,70)
33 | contents = new BorderPanel {
34 | add(new FlowPanel(A, B, X, ABLabel), BorderPanel.Position.North)
35 | }
36 | }
37 |
38 | override def live = _execute(liveScript)
39 | def liveScript: subscript.vm.Script[Any]
40 | def doExit = subscript.DSL._script[Any](None, Symbol("doExit")){(_node: subscript.vm.Script[Any]) =>
41 | implicit val script = _node
42 | subscript.DSL._alt(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => X), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => Key.Escape))}
43 |
44 | implicit def vkey(k: subscript.vm.FormalConstrainedParameter[Key.Value]): subscript.vm.Script[Any] = subscript.DSL._script[Any](None, Symbol("vkey"), k.~??(Symbol("k"))){(_node: subscript.vm.Script[Any]) =>
45 | implicit val script = _node
46 | subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => vkey2(subscript.DSL._maybeVarCall("top"), subscript.DSL._maybeVarCall("subscript.vm.ActualAdaptingParameter(k)")))}
47 | }
48 |
49 | object AsBX extends ABApplication {
50 | def getTitle = "A..; B; exit"
51 | override def liveScript = subscript.DSL._script[Any](None, Symbol("liveScript")){(_node: subscript.vm.Script[Any]) =>
52 | implicit val script = _node
53 | subscript.DSL._seq(subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => A), subscript.DSL._optionalBreak_loop), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => B), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => doExit))}
54 | }
55 | object AsBsX extends ABApplication {
56 | def getTitle = "A..B; exit"
57 | override def liveScript = subscript.DSL._script[Any](None, Symbol("liveScript")){(_node: subscript.vm.Script[Any]) =>
58 | implicit val script = _node
59 | subscript.DSL._seq(subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => A), subscript.DSL._optionalBreak_loop, subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => B)), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => doExit))}
60 | }
61 |
--------------------------------------------------------------------------------
/plugins/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val commonSettings = Seq(
2 | organization := "org.subscript-lang"
3 | , version := "3.0.5"
4 |
5 | , publishTo := {
6 | if (isSnapshot.value)
7 | Some("snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/")
8 | else
9 | Some("releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2")
10 | }
11 |
12 | , scalaVersion := "2.10.4"
13 |
14 | , pomExtra :=
15 | https://github.com/scala-subscript/subscript
16 |
17 |
18 | GNU GPL
19 | http://www.gnu.org/copyleft/gpl.html
20 | repo
21 |
22 |
23 |
24 | git://github.com/scala-subscript/subscript.git
25 | scm:git://github.com/scala-subscript/subscript.git
26 |
27 |
28 |
29 | anatoliykmetyuk
30 | Anatoliy Kmetyuk
31 | https://github.com/anatoliykmetyuk
32 |
33 |
34 | )
35 |
36 | lazy val root = (project in file ("."))
37 | .aggregate(parser, parserPlugin, enhancedMacros)
38 | .settings(
39 | packagedArtifacts := Map.empty // Don't publish root to maven
40 | )
41 |
42 | lazy val parser = (project in file("parser"))
43 | .settings(commonSettings)
44 | .settings(
45 | name := "subscript-parser"
46 | , crossScalaVersions := Seq("2.11.4", "2.10.5")
47 |
48 | , libraryDependencies ++= Seq(
49 | "com.lihaoyi" %% "acyclic" % "0.1.2" % "provided",
50 | "com.lihaoyi" %% "utest" % "0.3.0",
51 | "org.parboiled" %% "parboiled" % "2.1.0",
52 | "org.scalatest" %% "scalatest" % "2.2.4"
53 | )
54 |
55 | , addCompilerPlugin("com.lihaoyi" %% "acyclic" % "0.1.2")
56 | , autoCompilerPlugins := true
57 |
58 | , resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
59 | , testFrameworks += new TestFramework("utest.runner.Framework")
60 |
61 | , initialCommands := """
62 | |import util._
63 | |
64 | |import scalaParser._
65 | |import syntax._
66 | |import org.parboiled2._
67 | |
68 | |import scalaParser.subscript._
69 | |import ast.Ast._
70 | |
71 | |def p (in: String) = new Scala(in).CompilationUnit.run()
72 | |def ss(in: String) = new Scala(in).SubScriptCode.run()
73 | |def sp[T](p: Scala => Rule1[T], in: String): Try[T] = {
74 | | val parser = new Scala(in)
75 | | parser.__run(p(parser))
76 | |}
77 | """.stripMargin
78 |
79 | , excludeFilter in Test := "OperatorsSuite.scala" | "TermsSuite.scala" | "IntegratedSuite.scala"
80 | )
81 |
82 | lazy val parserPlugin = (project in file("plugin-parser"))
83 | .dependsOn(parser)
84 | .settings(commonSettings)
85 | .settings(
86 | name := "subscript-sbt-plugin"
87 | , sbtPlugin := true
88 | )
89 |
90 | lazy val enhancedMacros = (project in file("enhanced-macros"))
91 | .settings(commonSettings)
92 | .settings(
93 | scalaVersion := "2.11.7"
94 | , name := "enhancedmacros"
95 |
96 | , libraryDependencies ++= Seq(
97 | "org.scala-lang" % "scala-compiler" % "2.11.7"
98 | , "org.scala-lang" % "scala-reflect" % "2.11.7"
99 | )
100 | )
101 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/taskprocessor/Processor_rewritten.scala:
--------------------------------------------------------------------------------
1 | package subscript.example.taskprocessor.ssactors
2 | import subscript.file
3 |
4 | import akka.actor._
5 | import subscript.example.taskprocessor.Protocol._
6 |
7 | import subscript.Predef._
8 | import subscript.akka._
9 |
10 | /**
11 | * Receives tasks. Executes some job on data. Responds with success.
12 | * Maybe fails (on JVM fatal failure or ordinary exception) and stays silent.
13 | */
14 | class Processor[Df, Rf](processor: Df => Rf) extends SubScriptActor {
15 |
16 | var taskId : Long = -1
17 | var taskRequester: ActorRef = null
18 | var worker : Option[ActorRef] = None
19 |
20 |
21 | def live = subscript.DSL._script[Any](None, Symbol("live")){(_node: subscript.vm.Script[Any]) =>
22 | implicit val script = _node
23 | subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => task), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => success), subscript.DSL._loop)}
24 | def task = subscript.DSL._script[Any](None, Symbol("task")){(_node: subscript.vm.Script[Any]) =>
25 | implicit val script = _node
26 | subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => r$({
27 | case Task(data: Df, id) => subscript.DSL._maybeVarCall("sender ! ReceiptConfirmation(subscript.DSL._maybeVarCall(\"id\"))"); subscript.DSL._maybeVarCall("reset(subscript.DSL._maybeVarCall(\"Some(subscript.DSL._maybeVarCall(\\\"id\\\"))\"))"); subscript.DSL._maybeVarCall("process(subscript.DSL._maybeVarCall(\"data\"))")
28 | null
29 | }))}
30 | def success = subscript.DSL._script[Any](None, Symbol("success")){(_node: subscript.vm.Script[Any]) =>
31 | implicit val script = _node
32 | subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => r$({
33 | case s @ Success(id, Some(data: Rf)) if subscript.DSL._maybeVarCall("id == taskId && worker.exists(subscript.DSL._maybeVarCall(\"_ == sender\"))") =>
34 | subscript.DSL._maybeVarCall("taskRequester ! s")
35 | subscript.DSL._maybeVarCall("reset(subscript.DSL._maybeVarCall(\"None\"))")
36 |
37 | null
38 | }))}
39 | /*
40 | success = r$({
41 | case s @ Success(id, Some(data: Rf)) if id == taskId && worker.exists(_ == sender) =>
42 | taskRequester ! s
43 | reset(None)
44 | })
45 | */
46 |
47 |
48 | /**
49 | * This method controls state transmissions between `busy` and `idle`.
50 | */
51 | def reset(maybeId: Option[Long]) {
52 | // Set the internal state to its primeval condition
53 | taskId = -1
54 | taskRequester = null
55 | worker.foreach(context stop _) // Kill worker if it exists and processes (irrelevant) task
56 |
57 | // If there's a new task - set the state appropriately
58 | maybeId.foreach {id =>
59 | taskId = id
60 | taskRequester = sender
61 | }
62 | }
63 |
64 | /**
65 | * Spawns a worker and gives it a task to process.
66 | */
67 | def process(data: Df) {
68 | val task: () => Rf = () => processor(data)
69 | worker = Some(context actorOf Props(classOf[Worker[Rf]], task, taskId))
70 | }
71 |
72 | }
73 |
74 | /**
75 | * Does some actual job and responds with success.
76 | */
77 | class Worker[R](task: () => R, id: Long) extends Actor {
78 | context.parent ! Success[R](id, Some(task()))
79 | def receive = {case x => context.parent forward x}
80 | }
81 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/ab-example/Bag_AB_rewritten.scala:
--------------------------------------------------------------------------------
1 | package subscript.example
2 | import subscript.file
3 |
4 | import scala.swing._
5 | import scala.swing.event._
6 |
7 | import subscript.DSL._
8 |
9 | import subscript.swing.SimpleSubscriptApplication
10 | import subscript.swing.Scripts._
11 |
12 | // Subscript sample application: A..B
13 | //
14 | // Note: the main part of this source file has been manually compiled from Subscript code into plain Scala
15 |
16 | abstract class Bag_AB_Application extends SimpleSubscriptApplication {
17 | def getTitle: String
18 |
19 | val A = new Button("A") {enabled = false}
20 | val B = new Button("B") {enabled = false}
21 | val a = new Button("a") {enabled = false}
22 | val b = new Button("b") {enabled = false}
23 |
24 | val top = new MainFrame {
25 | title = getTitle
26 | location = new Point (800,0)
27 | preferredSize = new Dimension(400,70)
28 | contents = new BorderPanel {
29 | add(new FlowPanel(A, B, a, b), BorderPanel.Position.North)
30 | }
31 | }
32 | override def live = _execute(liveScript)
33 | def liveScript: subscript.vm.Script[Any]
34 | }
35 |
36 | object Bag_A extends Bag_AB_Application {
37 | def getTitle = "Bag: live = A (live&a)"
38 |
39 | override def liveScript = subscript.DSL._script[Any](None, Symbol("liveScript")){(_node: subscript.vm.Script[Any]) =>
40 | implicit val script = _node
41 | subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => A), subscript.DSL._par(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => liveScript), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => a)))}
42 | }
43 |
44 | object Bag_AB extends Bag_AB_Application {
45 | def getTitle = "Bag: live = A (live&a) + B (live&b)"
46 |
47 | override def liveScript = subscript.DSL._script[Any](None, Symbol("liveScript")){(_node: subscript.vm.Script[Any]) =>
48 | implicit val script = _node
49 | subscript.DSL._alt(subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => A), subscript.DSL._par(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => liveScript), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => a))), subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => B), subscript.DSL._par(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => liveScript), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => b))))}
50 | }
51 |
52 | object Bag_AB_loops extends Bag_AB_Application {
53 | def getTitle = "Bag = (A a & ..) & (B b & ..)"
54 |
55 | override def liveScript = subscript.DSL._script[Any](None, Symbol("liveScript")){(_node: subscript.vm.Script[Any]) =>
56 | implicit val script = _node
57 | subscript.DSL._par(subscript.DSL._par(subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => A), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => a)), subscript.DSL._optionalBreak_loop), subscript.DSL._par(subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => B), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => b)), subscript.DSL._optionalBreak_loop))}
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/syntax/Literals.scala:
--------------------------------------------------------------------------------
1 | package scalaParser
2 | package syntax
3 | import acyclic.file
4 | import org.parboiled2._
5 |
6 | trait Literals { self: Parser with Basic with Identifiers with RulesOps =>
7 | type R1 = Rule1[String]
8 |
9 | def Block: R1
10 | def WL: R1
11 | object Literals{
12 | import Basic._
13 | def Float: R1 = {
14 | def Thing = rule( Digit.+ ~ Exp.? ~ FloatType.? )
15 | def Thing2 = rule( "." ~ Thing | Exp ~ FloatType.? | Exp.? ~ FloatType )
16 | rule( capture("." ~ Thing | Digit.+ ~ Thing2) )
17 | }
18 |
19 | def Int: R1 = rule( capture((HexNum | DecNum) ~ anyOf("Ll").?) )
20 |
21 | def Bool: R1 = rule( capture(Key.W("true") | Key.W("false")) )
22 |
23 | def MultilineCommentR0: Rule0 = rule( "/*" ~ (MultilineCommentR0 | !"*/" ~ ANY).* ~ "*/" )
24 | // def MultilineComment : R1 = rule( capture("/*") ~ ((MultilineComment | capture(!"*/" ~ ANY)).* ~> ConcatSeqNoDelim) ~ capture("*/") ~> Concat3 )
25 | def MultilineComment: R1 = rule ( capture(MultilineCommentR0) )
26 |
27 | def CommentR0: Rule0 = rule(
28 | MultilineCommentR0 | "//" ~ (!Basic.Newline ~ ANY).* ~ &(Basic.Newline | EOI)
29 | )
30 | // def Comment: R1 = rule(
31 | // MultilineComment | capture("//" ~ (!Basic.Newline ~ ANY).* ~ &(Basic.Newline | EOI))
32 | // )
33 | def Comment: R1 = rule ( capture(CommentR0) )
34 |
35 |
36 | def Null: R1 = rule( capture(Key.W("null")) )
37 | def Literal: R1 = rule( (capture("-".?) ~ (Float | Int) ~> Concat) | Bool | Char | String | Symbol | Null )
38 |
39 | def EscapedChars: R1 = rule( capture('\\' ~ anyOf("btnfr'\\\"")) )
40 |
41 | // Note that symbols can take on the same values as keywords!
42 | def Symbol: R1 = rule( capture(''' ~ (Identifiers.PlainId | Identifiers.Keywords)) )
43 |
44 | def Char: R1 = {
45 | // scalac 2.10 crashes if PrintableChar below is substituted by its body
46 | def PrintableChar = CharPredicate.from(isPrintableChar)
47 |
48 | rule {
49 | capture("'") ~ (capture(UnicodeEscape) | EscapedChars | capture(!'\\' ~ PrintableChar)) ~ capture("'") ~> Concat3
50 | }
51 | }
52 |
53 |
54 | def pr(s: String): Rule0 = rule( run(println(s"LOGGING $cursor: $s")) )
55 | def Interp: R1 = rule{
56 | capture("$" ~ Identifiers.PlainIdNoDollar) | capture("${") ~ Block ~ WL ~ capture("}") ~> Concat4 | capture("$$")
57 | }
58 | def String: R1 = {
59 | import Identifiers.Id
60 | def InterpIf(b: Boolean): R1 = if(b) rule(Interp) else rule(capture(MISMATCH0))
61 | def TQ: Rule0 = rule( "\"\"\"" )
62 | def TripleChars(b: Boolean) = rule( (InterpIf(b) | capture('"'.? ~ '"'.? ~ noneOf("\"")) ).* ~> ConcatSeqNoDelim )
63 | def TripleTail: R1 = rule( capture(TQ ~ (zeroOrMore('"'))) )
64 | def SingleChars(b: Boolean): R1 = rule( ( InterpIf(b) | capture("\\\"") | capture("\\\\") | capture(noneOf("\n\"")) ).* ~> ConcatSeqNoDelim )
65 | rule {
66 | (capture(Id ~ TQ ) ~ TripleChars(b = true ) ~ TripleTail ~> Concat3) |
67 | (capture(Id ~ '"') ~ SingleChars(b = true ) ~ capture('"') ~> Concat3) |
68 | (capture(TQ ) ~ TripleChars(b = false) ~ TripleTail ~> Concat3) |
69 | (capture('"') ~ SingleChars(b = false) ~ capture('"') ~> Concat3)
70 | }
71 | }
72 |
73 | def isPrintableChar(c: Char): Boolean = {
74 | val block = Character.UnicodeBlock.of(c)
75 | !Character.isISOControl(c) && !Character.isSurrogate(c) && block != null && block != Character.UnicodeBlock.SPECIALS
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/plugins/plugin-parser/src/main/scala/subscript/plugin/SubscriptSbt.scala:
--------------------------------------------------------------------------------
1 | package subscript.plugin
2 |
3 | import scala.util._
4 |
5 | import sbt.Keys._
6 | import sbt._
7 |
8 | import org.parboiled2._
9 |
10 | import scalaParser._
11 | import scalaParser.subscript.parser.MarkerParser
12 |
13 | import sbt.Attributed.data
14 |
15 | object SubscriptSbt extends sbt.AutoPlugin with SubscriptSbtHelpers {
16 |
17 | def isSubscript(f: File): Boolean = if (f.exists && f.isFile) new MarkerParser(readFile(f)).Identify.run() match {
18 | case Success(flag: Boolean) => flag
19 | case Failure(e: ParseError) => parseError(e, f)
20 | }
21 | else false
22 |
23 | val subscriptFilter = new SimpleFileFilter(isSubscript)
24 |
25 | val mySeq = Seq(
26 | managedSources ++= (scalaSource.value ** "*.scala").get
27 | .filter(isSubscript)
28 | .map {in =>
29 | val outName = managedSourceDirectories.value.head.getAbsolutePath +
30 | in.getAbsolutePath.drop(scalaSource.value.getAbsolutePath.length)
31 | val out = new sbt.File(outName)
32 |
33 | val src = readFile(in)
34 |
35 | val settings = new MarkerParser(src).ExtractImports.run() match {
36 | case Success(imports) =>
37 | val pattern = """\s*import\s+subscript\.file\.parserSettings\.(.+)""".r
38 | imports.filter {pattern.findFirstIn(_).isDefined}.map {case pattern(setting) => setting}
39 | case Failure(_) => Nil
40 | }
41 |
42 | new Scala(readFile(in), settings).CompilationUnit.run() match {
43 | case Success(code ) => IO.write(out, code)
44 | case Failure(e: ParseError) => parseError(e, in )
45 | }
46 |
47 | out
48 | }
49 |
50 | , excludeFilter in unmanagedSources := (excludeFilter in unmanagedSources).value || subscriptFilter
51 | )
52 |
53 | lazy val ssDebug = taskKey[Unit]("Debug the main SubScript script with a debugger written in SubScript" )
54 | lazy val ssDebugPure = taskKey[Unit]("Debug the main SubScript script with a debugger written in pure Scala")
55 |
56 | override val projectSettings = inConfig(Test)(mySeq) ++ inConfig(Compile)(mySeq) ++ Seq(
57 | libraryDependencies ++= Seq(
58 | // "org.subscript-lang" % "subscript" % "1.0"
59 | // , "org.subscript-lang" % "subscript-swing" % "1.0"
60 | // , "org.scala-lang" % "scala-swing" % "2.11.0-M7"
61 | )
62 |
63 | , addCompilerPlugin("org.subscript-lang" %% "enhancedmacros" % "3.0.5")
64 |
65 | , ssDebug := {
66 | val r = (runner in Compile).value
67 | val mc = (mainClass in Compile).value.get
68 | val cp = (fullClasspath in Compile).value
69 | toError(r.run("subscript.swing.SubScriptDebugger", data(cp), Seq(mc), streams.value.log))
70 | }
71 |
72 | , ssDebugPure := {
73 | val r = (runner in Compile).value
74 | val mc = (mainClass in Compile).value.get
75 | val cp = (fullClasspath in Compile).value
76 | toError(r.run("subscript.swing.PureScalaDebugger", data(cp), Seq(mc), streams.value.log))
77 | }
78 | )
79 | }
80 |
81 | trait SubscriptSbtHelpers {this: AutoPlugin =>
82 | def readFile(f: File): String = io.Source.fromFile(f.getAbsolutePath).mkString
83 |
84 | def parseError(e: ParseError, file: File): Nothing = e match {case ParseError(Position(_, line, column), _, _) =>
85 | val lineStr = readFile(file).split("\n")(line - 1)
86 | val markerStr = " " * (column - 1) + "^"
87 | val filePath = file.getAbsolutePath
88 |
89 | val error = s"Parse error\nFile: $filePath\nError: $e\n$lineStr\n$markerStr"
90 | toError(Some(error)).asInstanceOf[Nothing]
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/scala/scalaParser/subscript/MigrationSuite.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript
2 |
3 | import scala.util._
4 |
5 | import org.parboiled2._
6 | import utest._
7 |
8 | import scalaParser.Scala
9 | import scalaParser.subscript.ast.Ast
10 |
11 | object MigrationSuite extends TestSuite with Checkers with Symbols {def tests = TestSuite {'subscript {
12 |
13 | // Braces
14 | * - checkExpr9("a [b | c]", s"$seq($a, $parOr($b, $c))")
15 |
16 | // Script calls
17 | * - checkExpr9("a: b, c" , s"""$scriptCall a($varCall("b"), $varCall("c")))""")
18 | * - checkExpr9("a: 1" , s"""$scriptCall a($varCall("1")))""" )
19 | * - checkExpr9("a: b c d", s"""$seq($scriptCall a($varCall("b"))), $c, $d)""" )
20 |
21 | * - checkExpr9(
22 | "while x"
23 | , s"""subscript.DSL._while (_node => {
24 | | implicit val here = _node
25 | |$varCall("x")
26 | |})""".stripMargin
27 | )
28 | * - checkExpr9(
29 | "while (!x)"
30 | , s"""subscript.DSL._while (_node => {
31 | | implicit val here = _node
32 | |$varCall("($varCall(\\"!x\\"))")
33 | |})""".stripMargin
34 | )
35 | * - checkExpr9(
36 | "while (!x)"
37 | , s"""subscript.DSL._while (_node => {
38 | | implicit val here = _node
39 | |$varCall("!x")
40 | |})""".stripMargin
41 | )
42 |
43 | // Scala code in scripts
44 | * - checkExpr9("a (b) c" , s"""$seq($a, $scriptCall $varCall("b")), $c)""")
45 | * - checkExpr9("a (b, c) d", s"""$seq($a, $scriptCall ($varCall("b"), $varCall("c"))), $d)""")
46 |
47 | // Code blocks
48 | * - checkExpr9(
49 | "{:a:}"
50 | , s"""$tiny[Any] ($nodeVal => {
51 | | implicit val $hereVal = $nodeVal
52 | |subscript.DSL._maybeVarCall("a")
53 | |}, true)""".stripMargin
54 | )
55 | * - checkExpr9(
56 | "{!a!}"
57 | , s"""$normal[Any] ($nodeVal => {
58 | | implicit val $hereVal = $nodeVal
59 | |subscript.DSL._maybeVarCall("a")
60 | |}, true)""".stripMargin
61 | )
62 |
63 | // Let statements
64 | * - checkExpr9(
65 | "let a = b"
66 | , s"""$tiny[Any] ($nodeVal => {
67 | | implicit val $hereVal = $nodeVal
68 | |$varCall("$varAss(\\"a\\", $varCall(\\"b\\"))")
69 | |}, true)""".stripMargin
70 | )
71 |
72 | * - checkExpr9(
73 | """a
74 | |let b
75 | |c""".stripMargin
76 | , s"""$seq($a, $tiny[Any] ($nodeVal => {
77 | | implicit val $hereVal = $nodeVal
78 | |$varCall("b")
79 | |}, true), $c)""".stripMargin
80 | )
81 |
82 | * - checkExpr9(
83 | "a let b; c"
84 | , s"""$seq($a, $tiny[Any] ($nodeVal => {
85 | | implicit val $hereVal = $nodeVal
86 | |$varCall("b")
87 | |}, true), $c)""".stripMargin
88 | )
89 |
90 | * - checkExpr9(
91 | "a let {b; c}; d"
92 | , s"""$seq($a, $tiny[Any] ($nodeVal => {
93 | | implicit val $hereVal = $nodeVal
94 | |$varCall("{$varCall(\\"b\\"); $varCall(\\"c\\")}")
95 | |}, true), $d)""".stripMargin
96 | )
97 |
98 | * - checkExpr9(
99 | "a let b c d; d"
100 | , s"""$seq($a, $tiny[Any] ($nodeVal => {
101 | | implicit val $hereVal = $nodeVal
102 | |$varCall("b c d")
103 | |}, true), $d)""".stripMargin
104 | )
105 |
106 |
107 | // Shorthand operators - ???
108 | // * - checkExpr9(
109 | // """+ if speed>minSpeed then speedDecButton
110 | // | if speedminSpeed")""")}($scriptCall speedDecButton)), ${iff(s"""$varCall("speed t.printStackTrace; throw t}
19 |
20 | override def main(args: Array[String]) = super.main(args)
21 |
22 | def liveScript = subscript.DSL._script[Any](None, Symbol("liveScript")){(_node: subscript.vm.Script[Any]) =>
23 | implicit val script = _node
24 | subscript.DSL._par_or2(subscript.DSL._seq(subscript.DSL._threaded[Any] (_node => {
25 | implicit val here = _node
26 | subscript.DSL._maybeVarCall("awaitMessageBeingHandled(subscript.DSL._maybeVarCall(\"true\"))")
27 | }, true), subscript.DSL._if (_node => {
28 | implicit val here = _node
29 | subscript.DSL._maybeVarCall("shouldStep")
30 | })(subscript.DSL._seq(subscript.DSL._at[subscript.vm.N_code_tiny[Any], subscript.vm.model.template.concrete.T_code_tiny[Any]](here => {
31 | implicit val there: subscript.vm.N_code_tiny[Any] = here.there;
32 | gui
33 | }).apply(subscript.DSL._tiny[Any] (_node => {
34 | implicit val here = _node
35 | subscript.DSL._maybeVarCall("updateDisplay")
36 | }, true)), subscript.DSL._par_or2(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => stepCommand), subscript.DSL._if (_node => {
37 | implicit val here = _node
38 | subscript.DSL._maybeVarCall("autoCheckBox.selected")
39 | })(subscript.DSL._threaded[Any] (_node => {
40 | implicit val here = _node
41 | subscript.DSL._maybeVarCall("waitForStepTimeout")
42 | }, true))))), subscript.DSL._normal[Any] (_node => {
43 | implicit val here = _node
44 | subscript.DSL._maybeVarCall("messageBeingHandled(subscript.DSL._maybeVarCall(\"false\"))")
45 | }, true), subscript.DSL._loop), subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => exitDebugger))}
46 | def stepCommand = subscript.DSL._script[Any](None, Symbol("stepCommand")){(_node: subscript.vm.Script[Any]) =>
47 | implicit val script = _node
48 | subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => stepButton)}
49 | def exitCommand = subscript.DSL._script[Any](None, Symbol("exitCommand")){(_node: subscript.vm.Script[Any]) =>
50 | implicit val script = _node
51 | subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => exitButton)}
52 | def exitDebugger = subscript.DSL._script[Any](None, Symbol("exitDebugger")){(_node: subscript.vm.Script[Any]) =>
53 | implicit val script = _node
54 | subscript.DSL._seq(subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => exitCommand), subscript.DSL._at[subscript.vm.N_code_normal[Any], subscript.vm.model.template.concrete.T_code_normal[Any]](here => {
55 | implicit val there: subscript.vm.N_code_normal[Any] = here.there;
56 | gui
57 | }).apply(subscript.DSL._normal[Any] (_node => {
58 | implicit val here = _node
59 | subscript.DSL._maybeVarCall("subscript.DSL._maybeVarAssignment(\"exitConfirmed\",subscript.DSL._maybeVarCall(\"confirmExit\"))")
60 | }, true)), subscript.DSL._while (_node => {
61 | implicit val here = _node
62 | subscript.DSL._maybeVarCall("!exitConfirmed")
63 | }))}
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/framework/swing/src/main/scala/swing/PureScalaDebugger.scala:
--------------------------------------------------------------------------------
1 | package subscript.swing
2 |
3 | import java.util.concurrent.Executors
4 |
5 | import scala.util.{Success, Failure}
6 | import scala.collection.mutable
7 |
8 | import scala.swing._
9 | import scala.swing.event._
10 |
11 | import scala.concurrent._
12 | import scala.concurrent.duration._
13 |
14 | object PureScalaDebugger extends PureScalaDebuggerApp
15 |
16 | class PureScalaDebuggerApp extends SimpleSwingApplication with GraphicalDebugger {
17 | implicit val executionContext = ExecutionContext fromExecutorService Executors.newCachedThreadPool()
18 |
19 | def live: Unit = {
20 | def again: Unit = Future {awaitMessageBeingHandled(true)}.flatMap {_ =>
21 | if (shouldStep) {
22 | Swing.onEDTWait(updateDisplay)
23 | Future firstCompletedOf Seq(stepCommand, autoStepCommand)
24 | } else Future.successful(())
25 | }.onComplete {
26 | case Success(_) =>
27 | messageBeingHandled(false)
28 | again
29 | case Failure(e) => e.printStackTrace()
30 | }
31 |
32 | again
33 |
34 | while (true) {
35 | waitForExit
36 | if (confirmExit) return
37 | }
38 | }
39 |
40 | // The reactorBank variable is needed to bypass a peculiarity of Scala Swing, which,
41 | // unfortunately, contains a bug.
42 | //
43 | // Publishers store their event listeners in the form of reaction functions.
44 | // Therefore, if you call listenTo(publisher) from a reactor, the reference
45 | // to this reactor will not be stored within the publisher. If there are no
46 | // other references to the reactor, it will be a subject for garbage collection.
47 | //
48 | // Publishers store the references to the reaction functions wrapped into a
49 | // java.lang.ref.WeakReference, which means that they will be garbage collected
50 | // if no other references to them exist.
51 | //
52 | // Given that typically the only other reference to a reaction function is
53 | // within a Reactor, it will be garbage collected together with the reactor.
54 | //
55 | // There are two solutions to this problem. The more elegant one is to add
56 | // override val reactions = new Reactions.Impl with Reactions.StronglyReferenced
57 | // to the anonymous reactors. This will make all the publishers to store
58 | // the reactions object as a strong reference rather then a weak one.
59 | // This approach doesn't work, however, due to the bug in Scala Swing, which doesn't
60 | // allow the reactors to unsubscribe from publishers if their reactions are StronglyReferenced.
61 | //
62 | // Another solution is to prevent the reactors themselves from the garbage collection
63 | // by storing them as a variable or in a collection.
64 | private[this] val reactorBank = mutable.ArrayBuffer[Reactor]()
65 | def futureButtonClick(button: Button): Future[Unit] = {
66 | val promise = Promise[Unit]()
67 | reactorBank += new Reactor {
68 | button.enabled = true
69 | listenTo(button)
70 | reactions += {
71 | case _: ButtonClicked =>
72 | promise.success(())
73 | button.enabled = false
74 |
75 | // Finalization logic
76 | deafTo(button)
77 | reactorBank -= this
78 | }
79 | }
80 | promise.future
81 | }
82 |
83 | def stepCommand = futureButtonClick(stepButton)
84 | def exitCommand = futureButtonClick(exitButton)
85 |
86 | def autoStepCommand: Future[Unit] = {
87 | lazy val never = Promise[Unit]().future
88 | if (autoCheckBox.selected) Future {waitForStepTimeout} else never
89 | }
90 |
91 | def waitForExit = Await.ready(exitCommand, Duration.Inf)
92 |
93 | override def main(args: Array[String]) = super.main(args)
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/plugins/parser/src/main/scala/scalaParser/subscript/parser/Core.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript
2 | package parser
3 |
4 | import language.implicitConversions
5 | import org.parboiled2._
6 | import scalaParser._
7 | import scalaParser.syntax._
8 |
9 | import scalaParser.subscript.ast.Ast
10 |
11 |
12 | trait Core {this: SubScript with Exprs =>
13 | def wspStrR0(s: String): R0 = rule( WLR0 ~ str(s))
14 | def wspChR0 (s: Char ): R0 = rule( WLR0 ~ ch (s))
15 |
16 | type R[T] = Rule1[T]
17 |
18 | def `script` = KeyWordOperators.W("script")
19 | def `let` = KeyWordOperators.W("let")
20 |
21 | def `..` = KeyWordOperators.O("..")
22 | def `+=` = KeyWordOperators.O("+=")
23 |
24 | def `|` = KeyWordOperators.O("|" )
25 | def `||` = KeyWordOperators.O("||" )
26 | def `&` = KeyWordOperators.O("&" )
27 | def `&&` = KeyWordOperators.O("&&" )
28 | def `==` = KeyWordOperators.O("==" )
29 | def plus = KeyWordOperators.O("+" )
30 | def `/` = KeyWordOperators.O("/" )
31 | def `%` = KeyWordOperators.O("%" )
32 | def `%/%/` = KeyWordOperators.O("%/%/")
33 | def `%/` = KeyWordOperators.O("%/" )
34 | def `%%` = KeyWordOperators.O("%%" )
35 | def `~~` = KeyWordOperators.O("~~" )
36 | def `+~/~` = KeyWordOperators.O("+~/~")
37 |
38 | def `<<` = KeyWordOperators.O("<<")
39 | def `>>` = KeyWordOperators.O(">>")
40 | def `==>` = KeyWordOperators.O("==>")
41 |
42 | def `^` = KeyWordOperators.O("^")
43 |
44 | def SSKeyword = rule (`then` | `script` | `let`)
45 | def SSOperator = rule (
46 | `|` | `||` | `&` | `&&` | `==` | plus | `/` | `%` | `%/%/` | `%/` | `%%` | capture(Basic.Newline)
47 | | `~~` | `+~/~` | `>>` | `==>`
48 | )
49 |
50 | def SSOperatorOrKeyword = rule (SSKeyword | SSOperator)
51 |
52 | def IdentedNewLine(col: Int): R0 = {
53 | def ValidCol: R0 = {
54 | val currentCol = Position(cursor, input).column
55 | if (currentCol > col) MATCH else MISMATCH0
56 | }
57 |
58 | rule { WSR0 ~ Basic.Newline ~ WLR0 ~ ValidCol }
59 | }
60 |
61 | def col = Position(cursor, input).column - 1 // computes the current column of the parser
62 |
63 | def IndentedNLSequence[T](r: () => R[T], minIndent: Int = Int.MaxValue): R[Seq[T]] = {
64 | lazy val col2 = math.min(col, minIndent)
65 | rule {WLR0 ~ Code {col2} ~ r().+(IdentedNewLine(col2))}
66 | }
67 |
68 | /**
69 | * Consumes all the white spaces (ws) before the rule r silently.
70 | */
71 | def Spaces[T](r: () => R[T], ws: () => R0 = () => WSR0): R[T] = rule { ws() ~ r() }
72 |
73 | def IdS : R1 = Spaces(() => Id)
74 | def StableIdS: R1 = Spaces(() => StableId)
75 |
76 | def Careted(r: () => R[Ast.Node], parseCaret: Boolean = true): R[Ast.Annotation] = {
77 | def MaybeCaret: R0 = if (parseCaret) rule {!WLOneOrMoreR0 ~ ch('^')} else rule {MATCH}
78 | rule {r() ~ MaybeCaret ~> {raw: Ast.Node => Ast.Annotation(Ast.Literal(ast.Constants.DSL.Op.CARET), raw)}}
79 | }
80 |
81 | def DoubleCareted(r: () => R[Ast.Node]): R[Ast.Annotation] =
82 | rule {r() ~ !WLOneOrMoreR0 ~ str("^^") ~> {raw: Ast.Node => Ast.Annotation(Ast.Literal(ast.Constants.DSL.Op.DOUBLE_CARET), raw)}}
83 |
84 | def DoubleCaretedNumber(r: () => R[Ast.Node]): R[Ast.Annotation] =
85 | rule {r() ~ !WLOneOrMoreR0 ~ str("^^") ~ !WLOneOrMoreR0 ~ Literals.Int ~> {(raw: Ast.Node, num: String) => Ast.Annotation(Ast.Literal(s"${ast.Constants.DSL.Op.DOUBLE_CARET_NUMBER}(${num.toInt})"), raw)}}
86 | }
87 |
88 | trait HighPriorityRulesConversions extends RuleDSLBasics {this: SubScript with Exprs =>
89 | implicit def wspStrR1(s: String): R1 = rule( capture(wspStrR0(s)) )
90 | implicit def wspChR1 (s: Char ): R1 = rule( capture(wspChR0 (s)) )
91 | }
92 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/scala/scalaParser/subscript/Symbols.scala:
--------------------------------------------------------------------------------
1 | package scalaParser.subscript
2 |
3 | import scalaParser.subscript.ast.Constants._
4 | import scalaParser.subscript.ast.Constants.DSL._
5 |
6 | trait Symbols {
7 | def dsl(method: String) = s"subscript.DSL.$method"
8 | def call(sym: String ) = s"""subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) => ${varc('"' + sym + '"')})"""
9 | def varc(sym: String) = s"""subscript.DSL._maybeVarCall($sym)"""
10 | def script(name: String) = s"""subscript.DSL._script[Any](None, Symbol("$name")){(_node: subscript.vm.Script[Any]) =>
11 | | implicit val script = _node""".stripMargin
12 |
13 | def script(name: String, body: String) =
14 | s"""subscript.DSL._script[Any](None, Symbol("$name")){(_node: subscript.vm.Script[Any]) =>
15 | | implicit val script = _node
16 | |$body}""".stripMargin
17 |
18 | def lambda(body: String) = script("", body)
19 |
20 | def ifBase(method: String, condition: String) =
21 | s"""$method (_node => {
22 | | implicit val here = _node
23 | |${condition}
24 | |})""".stripMargin
25 | def iff (condition: String) = ifBase(ifOp , condition)
26 | def iffElse(condition: String) = ifBase(ifElse, condition)
27 |
28 | def annotation(body: String, target: String, nType: String = Type.CALL_GRAPH_NODE, tType: String = Type.TEMPLATE_CHILD) =
29 | s"""${Term.ANNOTATION}[$nType, $tType](${Name.HERE} => {
30 | | implicit val ${Name.THERE}: $nType = here.there;
31 | |$body
32 | |}).apply($target)""".stripMargin
33 |
34 |
35 |
36 | val seq = dsl("_seq")
37 | val ifOp = dsl("_if")
38 | val ifElse = dsl("_if_else")
39 | val doThen = dsl("_do_then")
40 | val doThenElse = dsl("_do_then_else")
41 | val doElse = dsl("_do_else")
42 | val parOr = dsl("_par_or" )
43 | val parOr2 = dsl("_par_or2")
44 | val par = dsl("_par")
45 | val parAnd2 = dsl("_par_and2")
46 | val parEqual = dsl("_par_equal")
47 | val alt = dsl("_alt")
48 |
49 | val disrupt = dsl("_disrupt")
50 | val shuffle = dsl("_shuffle")
51 | val shuffle1OrMore = dsl("_shuffle_1_or_more")
52 | val interrupt = dsl("_interrupt")
53 | val interrupt0OrMore = dsl("_interrupt_0_or_more")
54 |
55 | val normal0 = dsl("_normal0")
56 | val threaded0 = dsl("_threaded0")
57 | val unsure0 = dsl("_unsure0")
58 | val tiny0 = dsl("_tiny0")
59 | val eventhandling0 = dsl("_eventhandling0")
60 | val eventhandling_loop0 = dsl("_eventhandling_loop0")
61 |
62 | val normal = dsl("_normal")
63 | val threaded = dsl("_threaded")
64 | val unsure = dsl("_unsure")
65 | val tiny = dsl("_tiny")
66 | val eventhandling = dsl("_eventhandling")
67 | val eventhandling_loop = dsl("_eventhandling_loop")
68 |
69 | val a = call("a")
70 | val b = call("b")
71 | val c = call("c")
72 | val d = call("d")
73 | val e = call("e")
74 | val f = call("f")
75 |
76 | val launchAnchor = dsl("_launch_anchor")
77 | val launch = dsl("_launch" )
78 |
79 | val scriptCall = s"""subscript.DSL._maybeCall("", (here: subscript.vm.model.callgraph.CallGraphTreeNode) =>"""
80 | val varCall = "subscript.DSL._maybeVarCall"
81 | val varAss = "subscript.DSL._maybeVarAssignment"
82 | val actorCall = s"$scriptCall r$$"
83 |
84 | val nodeVal = "_node"
85 | val hereVal = "here"
86 | val scriptVal = "`script`"
87 |
88 | val dfThen = dsl("_dataflow_then")
89 | val dfThenElse = dsl("_dataflow_then_else")
90 |
91 | val loop = dsl("_loop")
92 | val optLoop = dsl("_optionalBreak_loop")
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/framework/core/shared/src/main/scala/subscript/CorePredef.scala:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of Subscript - an extension of the Scala language
3 | with constructs from Process Algebra.
4 |
5 | Subscript is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License and the
7 | GNU Lesser General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | Subscript consists partly of a "virtual machine". This is a library;
12 | Subscript applications may distribute this library under the
13 | GNU Lesser General Public License, rather than under the
14 | GNU General Public License. This way your applications need not
15 | be made Open Source software, in case you don't want to.
16 |
17 | Subscript is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You may have received a copy of the GNU General Public License
23 | and the GNU Lesser General Public License along with Subscript.
24 | If not, see
25 | */
26 |
27 | package subscript
28 |
29 | import scala.util.{Try,Success,Failure}
30 |
31 | import subscript.vm._
32 | import subscript.DSL._
33 | import subscript.vm.executor._
34 | import subscript.vm.model.template._
35 | import subscript.vm.model.template.concrete._
36 | import subscript.vm.model.callgraph._
37 | import subscript.vm.model.callgraph.generic._
38 |
39 | // Predefined stuff - pass and some scripts: times, delta, epsilon, nu
40 | //
41 | object CorePredef extends CorePredefTrait
42 | trait CorePredefTrait {
43 |
44 | def `$` [R] (implicit s: ScriptTrait[R]): Try[R] = s.$
45 | def `$success` [R] (implicit s: ScriptTrait[R]): R = s.$ match {case Success(s) => s case null => null.asInstanceOf[R]}
46 | def `$failure` [R] (implicit s: ScriptTrait[R]): Throwable = s.$ match {case Failure(f) => f case null => null}
47 | def `$_=` [R] (v: Try[R] )(implicit s: ScriptTrait[R]) = {s.$=v; v match {case Failure(_) => s.fail /*; println("$=Failure(_)")*/ case _ => }}
48 | def `$success_=`[R] (v: R )(implicit s: ScriptTrait[R]) = {s.$=Success(v)}
49 | def `$failure_=`[R] (v: Throwable)(implicit s: ScriptTrait[R]) = {s.$=Failure(v); s.fail /*; println("$failure_=")*/}
50 |
51 | def pass (implicit node: CallGraphTreeNode): Int = node.pass
52 | def pass_up1(implicit node: CallGraphTreeNode): Int = node.n_ary_op_ancestor.pass
53 | def pass_up2(implicit node: CallGraphTreeNode): Int = node.n_ary_op_ancestor.n_ary_op_ancestor.pass
54 |
55 |
56 | def runScript[S ](_script: Script[S] ): ScriptExecutor[S] = DSL._execute(_script )
57 | def runScript[S<:X,X](_script: Script[S], executor: ScriptExecutor[X]): ScriptExecutor[X] = DSL._execute(_script, executor )
58 | def runScript[S ](_script: Script[S], debugger: MsgListener ): ScriptExecutor[S] = DSL._execute(_script, debugger )
59 | def runScript[S ](_script: Script[S], allowDebugger: Boolean ): ScriptExecutor[S] = DSL._execute(_script, allowDebugger)
60 |
61 | def runScript[S ](_script: Script[S], debugger: MsgListener, allowDebugger: Boolean ): ScriptExecutor[S] = DSL._execute(_script, debugger, allowDebugger)
62 | def runScript[S<:X,X](_script: Script[S], debugger: MsgListener, executor: ScriptExecutor[X]): ScriptExecutor[X] = DSL._execute(_script, debugger, executor)
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/framework/core-scripts/src/test/scala/subscript/CaretSuite.scala:
--------------------------------------------------------------------------------
1 | package subscript
2 |
3 | import scala.util._
4 |
5 | import subscript.language
6 | import subscript.Predef._
7 |
8 | import org.scalatest._
9 |
10 | class CaretSuite extends FlatSpec with Matchers
11 | with CommonHelpers {
12 |
13 | "Caret" should "work with code blocks" in {
14 | [
15 | {!1!}^ {!2!}
16 | ].e shouldBe Success(1)
17 | }
18 |
19 | it should "work with script calls" in {
20 | [
21 | n1 n2^
22 | ].e shouldBe Success(2)
23 | }
24 |
25 | it should "work with parenthesised code" in {
26 | [
27 | {!10!} [n1^ n2]^
28 | ].e shouldBe Success(1)
29 | }
30 |
31 | it should "work in prefix position before the literals" in {
32 | [^1 n2 ].e shouldBe Success(1 )
33 | [n1 ^"foo" n2].e shouldBe Success("foo")
34 | [n1 n2 ^true ].e shouldBe Success(true )
35 | }
36 |
37 | it should "work in prefix position before tuples" in {
38 | [n1 ^(1, 2) n2].e shouldBe Success((1, 2))
39 | }
40 |
41 | it should "work in prefix position before expressions" in {
42 | [n1 ^(2 + 3) n2].e shouldBe Success(5)
43 | }
44 |
45 | it should "work in prefix position before vars" in {
46 | [
47 | var x: Int = 3
48 | ^x
49 | ].e shouldBe Success(3)
50 | }
51 |
52 | it should "work in prefix position before complex var/method calls" in {
53 | object foo {
54 | class Bar(x: Int) {
55 | def getX = x
56 | def get(y: Int) = y
57 | }
58 |
59 | def bar(x: Int) = new Bar(x)
60 | }
61 |
62 | var i = 0
63 |
64 | script s =
65 | ^foo.bar(1).getX ~~(x: Int)~~> let i += x
66 | ^foo.bar(1).get(2) ~~(x: Int)~~> let i += x
67 | ^foo.bar(1).get: 2 ~~(x: Int)~~> let i += x
68 |
69 | runScript(s)
70 |
71 | i shouldBe 5
72 | }
73 |
74 | "Double caret" should "work with code blocks" in {
75 | [times: 5 {!here.pass!}^^].e shouldBe Success((0 to 4).toSeq)
76 | }
77 |
78 | it should "work with script calls" in {
79 | [times: 5 n1^^].e shouldBe Success((0 to 4).map(x => 1).toSeq)
80 | }
81 |
82 | it should "work with literals" in {
83 | [times: 5 ^1^^].e shouldBe Success((0 to 4).map(x => 1).toSeq)
84 | }
85 |
86 | it should "work with tuples" in {
87 | [times: 5 ^(1, 2)^^].e shouldBe Success((0 to 4).map(x => (1, 2)).toSeq)
88 | }
89 |
90 | it should "work with vars" in {
91 | [
92 | var x: Int = 3
93 | ^x^^
94 | ].e shouldBe Success(Seq(3))
95 | }
96 |
97 | it should "populate unsuccessful passes with nulls" in {
98 | ([@{there.pass = 2}: ^1^^]).e shouldBe Success(Seq(null, null, 1 ))
99 | ([@{there.pass = 1}: ^1^^ @{there.pass = 3}: ^2^^]).e shouldBe Success(Seq(null, 1 , null, 2))
100 | }
101 |
102 | "Double caret with numbers" should "work with code blocks" in {
103 | [{!1!}^^1 {!2!}^^2].e shouldBe Success((1, 2))
104 | }
105 |
106 | it should "work with script calls" in {
107 | [n1^^2 n2^^1].e shouldBe Success((2, 1))
108 | }
109 |
110 | it should "work with literals" in {
111 | [^1^^3 ^2^^1].e shouldBe Success((2, null, 1))
112 | }
113 |
114 | it should "work for tuples" in {
115 | [^(1, 2)^^1 ^(2, 3)^^2].e shouldBe Success( ((1, 2), (2, 3)) )
116 | }
117 |
118 | it should "work with vars" in {
119 | [
120 | var x: Int = 3
121 | ^x^^1 ^x^^2
122 | ].e shouldBe Success((3, 3))
123 | }
124 |
125 | "Implicit caret" should "work in case of a script containing one argument of type T_code_fragment or T_call" in {
126 | def foo: Unit = ()
127 | ([@foo: n1]).e shouldBe Success(1)
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/life-example/BasicLifeFrame.scala:
--------------------------------------------------------------------------------
1 | package subscript.example.life
2 | import subscript.file
3 |
4 | import scala.swing._
5 | import scala.swing.event._
6 | import subscript.DSL._
7 | import subscript.swing.SimpleSubscriptApplication
8 | import subscript.vm.executor._
9 |
10 | // object BasicLifeFrame extends BasicLifeFrameApplication
11 | class BasicLifeFrameApplication extends SimpleSubscriptApplication {
12 |
13 | val board = new LifeBoard
14 | val startButton = new Button("Start" ) {enabled = false; focusable = false}
15 | val stopButton = new Button("Stop" ) {enabled = false; focusable = false}
16 | val stepButton = new Button("Step" ) {enabled = false; focusable = false}
17 | val randomizeButton = new Button("Random") {enabled = false; focusable = false}
18 | val clearButton = new Button("Clear" ) {enabled = false; focusable = false}
19 | val minSpeedButton = new Button("<<" ) {enabled = false; focusable = false; size.width = 20}
20 | val slowerButton = new Button("<" ) {enabled = false; focusable = false; size.width = 20}
21 | val fasterButton = new Button(">" ) {enabled = false; focusable = false; size.width = 20}
22 | val maxSpeedButton = new Button(">>" ) {enabled = false; focusable = false; size.width = 20}
23 | val exitButton = new Button("Exit" ) {enabled = false; focusable = false}
24 | val speedLabel = new Label("speed" ) {preferredSize = new Dimension(65,26)}
25 | val speedSlider = new Slider {min = 1; max = 10}
26 |
27 | val NO_PATTERN = "Toggle Cell"
28 | val patternList = new ListView[String] {listData = NO_PATTERN::ConwayPatterns.allPatterns.map(_._1); selectIndices(0)}
29 |
30 | def selectedPatternName_notWorking = patternList.selection.items.head // does not get updated...bug in Scala/Java Swing
31 | def selectedPatternName = patternList.listData(patternList.selection.leadIndex)
32 | def selectedPattern:Option[String] = {
33 | //println(s"selectedPattern: ${patternList.selection.items}")
34 | //println(s"selectedPattern: ${patternList.selection.leadIndex}")
35 | //println(s"selectedPattern: $selectedPatternName")
36 | if (selectedPatternName==NO_PATTERN) None
37 | else ConwayPatterns.allPatterns.toMap.get(selectedPatternName)
38 | }
39 | val top = new MainFrame {
40 | title = "Life - Subscript"
41 | location = new Point (100,100)
42 | preferredSize = new Dimension(600,400)
43 | contents = new BorderPanel {
44 | add(new BorderPanel {
45 | add (new FlowPanel(startButton, stopButton, stepButton, randomizeButton, clearButton, exitButton), BorderPanel.Position.North)
46 | add (new FlowPanel(speedLabel , minSpeedButton, slowerButton, speedSlider, fasterButton, maxSpeedButton), BorderPanel.Position.South)
47 | } , BorderPanel.Position.North)
48 | add(new BorderPanel {
49 | add (new ScrollPane(patternList) {verticalScrollBarPolicy = ScrollPane.BarPolicy.Always; listenTo(keys)}, BorderPanel.Position.West)
50 | add (board, BorderPanel.Position.Center)
51 | }, BorderPanel.Position.Center)
52 | }
53 | }
54 |
55 | // try to listen to the key events....
56 | top.contents.head.focusable = true
57 | top.contents.head.requestFocus
58 | top.listenTo(patternList.keys)
59 | top.listenTo(speedSlider.keys)
60 | top.listenTo(top.contents.head.keys)
61 |
62 | val f = top.peer.getRootPane().getParent().asInstanceOf[javax.swing.JFrame]
63 | f.setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE) // TBD: does not seem to work on MacOS
64 |
65 | def minSpeed = speedSlider.min
66 | def maxSpeed = speedSlider.max
67 | def speed = speedSlider.value
68 | def setSpeedValue(s: Int) {
69 | speedLabel.text = "Speed: " + s
70 | speedSlider.value = s
71 | }
72 |
73 | setSpeedValue(9)
74 |
75 | override def live = _execute(liveScript)
76 |
77 | def sleep(t: Long): Unit = Thread.sleep(t)
78 | override script..
79 | liveScript = {*sleep(34567)*}
80 | }
81 |
--------------------------------------------------------------------------------
/plugins/parser/src/test/resources/subscript/examples/life-example/BasicLifeFrame_rewritten.scala:
--------------------------------------------------------------------------------
1 | package subscript.example.life
2 | import subscript.file
3 |
4 | import scala.swing._
5 | import scala.swing.event._
6 | import subscript.DSL._
7 | import subscript.swing.SimpleSubscriptApplication
8 | import subscript.vm.executor._
9 |
10 | // object BasicLifeFrame extends BasicLifeFrameApplication
11 | class BasicLifeFrameApplication extends SimpleSubscriptApplication {
12 |
13 | val board = new LifeBoard
14 | val startButton = new Button("Start" ) {enabled = false; focusable = false}
15 | val stopButton = new Button("Stop" ) {enabled = false; focusable = false}
16 | val stepButton = new Button("Step" ) {enabled = false; focusable = false}
17 | val randomizeButton = new Button("Random") {enabled = false; focusable = false}
18 | val clearButton = new Button("Clear" ) {enabled = false; focusable = false}
19 | val minSpeedButton = new Button("<<" ) {enabled = false; focusable = false; size.width = 20}
20 | val slowerButton = new Button("<" ) {enabled = false; focusable = false; size.width = 20}
21 | val fasterButton = new Button(">" ) {enabled = false; focusable = false; size.width = 20}
22 | val maxSpeedButton = new Button(">>" ) {enabled = false; focusable = false; size.width = 20}
23 | val exitButton = new Button("Exit" ) {enabled = false; focusable = false}
24 | val speedLabel = new Label("speed" ) {preferredSize = new Dimension(65,26)}
25 | val speedSlider = new Slider {min = 1; max = 10}
26 |
27 | val NO_PATTERN = "Toggle Cell"
28 | val patternList = new ListView[String] {listData = NO_PATTERN::ConwayPatterns.allPatterns.map(_._1); selectIndices(0)}
29 |
30 | def selectedPatternName_notWorking = patternList.selection.items.head // does not get updated...bug in Scala/Java Swing
31 | def selectedPatternName = patternList.listData(patternList.selection.leadIndex)
32 | def selectedPattern:Option[String] = {
33 | //println(s"selectedPattern: ${patternList.selection.items}")
34 | //println(s"selectedPattern: ${patternList.selection.leadIndex}")
35 | //println(s"selectedPattern: $selectedPatternName")
36 | if (selectedPatternName==NO_PATTERN) None
37 | else ConwayPatterns.allPatterns.toMap.get(selectedPatternName)
38 | }
39 | val top = new MainFrame {
40 | title = "Life - Subscript"
41 | location = new Point (100,100)
42 | preferredSize = new Dimension(600,400)
43 | contents = new BorderPanel {
44 | add(new BorderPanel {
45 | add (new FlowPanel(startButton, stopButton, stepButton, randomizeButton, clearButton, exitButton), BorderPanel.Position.North)
46 | add (new FlowPanel(speedLabel , minSpeedButton, slowerButton, speedSlider, fasterButton, maxSpeedButton), BorderPanel.Position.South)
47 | } , BorderPanel.Position.North)
48 | add(new BorderPanel {
49 | add (new ScrollPane(patternList) {verticalScrollBarPolicy = ScrollPane.BarPolicy.Always; listenTo(keys)}, BorderPanel.Position.West)
50 | add (board, BorderPanel.Position.Center)
51 | }, BorderPanel.Position.Center)
52 | }
53 | }
54 |
55 | // try to listen to the key events....
56 | top.contents.head.focusable = true
57 | top.contents.head.requestFocus
58 | top.listenTo(patternList.keys)
59 | top.listenTo(speedSlider.keys)
60 | top.listenTo(top.contents.head.keys)
61 |
62 | val f = top.peer.getRootPane().getParent().asInstanceOf[javax.swing.JFrame]
63 | f.setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE) // TBD: does not seem to work on MacOS
64 |
65 | def minSpeed = speedSlider.min
66 | def maxSpeed = speedSlider.max
67 | def speed = speedSlider.value
68 | def setSpeedValue(s: Int) {
69 | speedLabel.text = "Speed: " + s
70 | speedSlider.value = s
71 | }
72 |
73 | setSpeedValue(9)
74 |
75 | override def live = _execute(liveScript)
76 |
77 | def sleep(t: Long): Unit = Thread.sleep(t)
78 | override def liveScript = subscript.DSL._script[Any](None, Symbol("liveScript")){(_node: subscript.vm.Script[Any]) =>
79 | implicit val script = _node
80 | subscript.DSL._threaded[Any] (_node => {
81 | implicit val here = _node
82 | subscript.DSL._maybeVarCall("sleep(subscript.DSL._maybeVarCall(\"34567\"))")
83 | }, true)}
84 | }
85 |
--------------------------------------------------------------------------------