├── 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 | --------------------------------------------------------------------------------