Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Scripting #77

Merged
merged 6 commits into from Jun 13, 2018
Merged

Scripting #77

merged 6 commits into from Jun 13, 2018

Conversation

ligee
Copy link
Member

@ligee ligee commented Aug 1, 2017

No description provided.


`kotlinc -script myscript.kts`

Or with some hypothetical dedicated runner, that we might want to include into the distribution:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's already a non-hypothetical dedicated runner called kotlin that we include into the distribution today, let's use it.


Or with some hypothetical dedicated runner, that we might want to include into the distribution:

`kotlinsh myscrtipt.ktsh`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be

kotlin myscript.kts

To be able to use the Kotlin scripts in a Unix shell environment, the *shebang* (`#!`) syntax should be supported
at the beginning of the script:
```
#! /path/to/kotlin/script/runner -some -params
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an aside, note that there may be problems with passing multiple arguments in the shebang line: https://stackoverflow.com/a/4304187/288456

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks, I remember that. Therefore the syntax of passing params in the arguments to the annotations should be supported as well.

parameters, e.g.:

```
@file:param("name", String::class)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the ::class literal, you can only reference a class, not a type. For example, this way you can't specify a parameter with the type String?, or List<String>.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a less restrictive way to do it? (besides the stringly typing)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there's no way to reference a type in an annotation, see #39

**Script Definition** is a configuration entity that combines platform, preprocessor, and selector in one entity
for simplified discovery and configuration.

The definition is a kotlin class declaration annotated with specific annotations. The class should be defined in the SAM
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be an interface?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see the reason why not. I'll fix the description.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it have to be abstract? We could use an annotation like @ScriptBody so that the script is generated into an override, no matter whether the member was abstract or not. Must not be final though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, can it be a property, not a function?

Copy link
Member Author

@ligee ligee Aug 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abreslav do you see it as an addition? I'm fine with the @ScriptBody annotation, but I think that using SAM notation by default is quite convenient.
And what would be the use of the non-abstract script body method?

```
interface ScriptingPlatform<CompilationConfig> {
fun compile(scriptSource, scriptBaseClass: KClass<Scritpt>, compilationConfig: CompilationConfig): KClass<out Script>
fun <getIdeData>(scriptSource, scriptBaseClass: KClass<Script>, compilationConfig: CompilationConfig): <IdeData>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this notation mean?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you mean angle brackets - it means that I cannot figure out names yet. Something I need to discuss with Pavel yet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, maybe it should be explained in the document because I was really confused. Maybe just use some names, and explain that those are tentative

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

The `CompilationConfig` for the JVM platform may look like:
```
interface KotlinJVMScriptAdditionalParameters {
val classpath: Iterable<File> // dependencies classpath
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also have module path + names of modules to load, for Java 9+?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, anything that platform needs, this is just an example. The actual definition of the CompilationConfig should not be specified, but rather taken from the platform definition.


- **Script** - a text file written in Kotlin language but allowing top-level statements and having access to some
implicit (not directly mentioned in the script text) properties, as if the whole script body is a body of an implicit
function
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why just properties?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant parameters in fact. But the statement is ambiguous since we assume some implicit imports that are not referenced in the body as well.

function
- **(Scripting) Host** - an application or a component which handles script execution
- **REPL line** - a group of script text lines, executed in a single REPL eval call (*confusingly - a line == many text
lines, so maybe another term is needed.*)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terminology option:

  • REPL statement

### Project-level scripting

Applications: test definition scripts (Spek), ktor routing scripts, project-level REPL, build scripts, type safe
config files, etc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is Ktor privileged here?

environment, supplying any arguments that the script requires:
- `(compiledScript, compilationConfig, environment) -> scriptObject`
- `(scriptObject, compilationConfig, environment) -> Unit`
- uses `compilationConfig` and `environment` for "feeding" the script with the arguments
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If "feeding" is not a specially coined term, replace it with "passing arguments to the script"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is more like "to compute arguments for the script"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this means that I misunderstood the purpose of this, because of this terminonlgy

scripting host
- **Selector** - receives the script file and/or text before further analysis to determine whether the script belongs
to this scripting host and the particular set of components
- `(scriptSource) -> Boolean`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the file name belong to scriptSource?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I meant that scriptSource (as ScriptContent class now) references the script either by file path or by contents or both.

```
interface ScriptingPlatform<CompilationConfig> {
fun compile(scriptSource, scriptBaseClass: KClass<Scritpt>, compilationConfig: CompilationConfig): KClass<out Script>
fun <getIdeData>(scriptSource, scriptBaseClass: KClass<Script>, compilationConfig: CompilationConfig): <IdeData>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1


```
interface ScriptPreprocessor<CompilationConfig> {
fun preprocess(scriptSource): CompilationConfig
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to clarify what "scriptSource" is here. Bot the file name and file contents should be available through it, IMO, but maybe something else too


```
interface ScriptSelector {
fun isScript(scriptSource): boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most like likely a bad name. Is it really checking whether this is a script or not? I thought that it was checking whether this script can be processed by something (what is it, btw: platform, host, definition?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I was playing with isKnownScript name as well, but it looked cumbersome. May be it is the better one anyway.

- choose appropriate preprocessor or implement custom
- choose/implement selector
- define script class with the `@ScriptDefinition` annotation
- implement executor for the script class
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do I do with all these implementations?

Copy link
Member Author

@ligee ligee Aug 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are used in the parts 2) and 3)

- call platform to compile script
- call execute to get an instance
- call executor to run the script instance
- *(the base host may implement most of the boilerplate)*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not clear which APIs I can use while doing this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be best to have a sample that does all this to refer to

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants