Introduce some new standard library modules
This commit is contained in:
@@ -15,7 +15,7 @@ function _flatten(list: list, output: list) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extend list as this {
|
extend list as this {
|
||||||
function toFlat() {
|
function flatten() {
|
||||||
return flatten(this);
|
return flatten(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +23,16 @@ extend list as this {
|
|||||||
return (this as item ^ item % item == value).size > 0;
|
return (this as item ^ item % item == value).size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function indexOf(value) {
|
||||||
|
this as (item, index) ^ {
|
||||||
|
if(item == value) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
function join(separator: string = ", ") {
|
function join(separator: string = ", ") {
|
||||||
output = ""
|
output = ""
|
||||||
this as (item, index) ^ {
|
this as (item, index) ^ {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package io.smnp.ext.lang
|
package io.smnp.ext.lang
|
||||||
|
|
||||||
import io.smnp.ext.NativeModuleProvider
|
import io.smnp.ext.NativeModuleProvider
|
||||||
|
import io.smnp.ext.lang.constructor.IntConstructor
|
||||||
|
import io.smnp.ext.lang.constructor.NoteConstructor
|
||||||
import io.smnp.ext.lang.function.TypeOfFunction
|
import io.smnp.ext.lang.function.TypeOfFunction
|
||||||
import io.smnp.ext.lang.method.CharAtMethod
|
import io.smnp.ext.lang.method.CharAtMethod
|
||||||
import io.smnp.ext.lang.method.ListAccessMethod
|
import io.smnp.ext.lang.method.ListAccessMethod
|
||||||
@@ -9,6 +11,6 @@ import org.pf4j.Extension
|
|||||||
|
|
||||||
@Extension
|
@Extension
|
||||||
class LangModule : NativeModuleProvider("smnp.lang") {
|
class LangModule : NativeModuleProvider("smnp.lang") {
|
||||||
override fun functions() = listOf(TypeOfFunction())
|
override fun functions() = listOf(IntConstructor(), NoteConstructor(), TypeOfFunction())
|
||||||
override fun methods() = listOf(ListAccessMethod(), MapAccessMethod(), CharAtMethod())
|
override fun methods() = listOf(ListAccessMethod(), MapAccessMethod(), CharAtMethod())
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package io.smnp.ext.lang.constructor
|
||||||
|
|
||||||
|
import io.smnp.callable.function.Function
|
||||||
|
import io.smnp.callable.function.FunctionDefinitionTool
|
||||||
|
import io.smnp.callable.signature.Signature.Companion.simple
|
||||||
|
import io.smnp.type.enumeration.DataType.FLOAT
|
||||||
|
import io.smnp.type.enumeration.DataType.INT
|
||||||
|
import io.smnp.type.matcher.Matcher.Companion.ofType
|
||||||
|
import io.smnp.type.model.Value
|
||||||
|
|
||||||
|
class IntConstructor : Function("Int") {
|
||||||
|
override fun define(new: FunctionDefinitionTool) {
|
||||||
|
new function simple(ofType(INT)) body { _, (int) ->
|
||||||
|
int
|
||||||
|
}
|
||||||
|
|
||||||
|
new function simple(ofType(FLOAT)) body { _, (float) ->
|
||||||
|
Value.int((float.value as Float).toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package io.smnp.ext.lang.constructor
|
||||||
|
|
||||||
|
import io.smnp.callable.function.Function
|
||||||
|
import io.smnp.callable.function.FunctionDefinitionTool
|
||||||
|
import io.smnp.callable.signature.Signature.Companion.simple
|
||||||
|
import io.smnp.data.entity.Note
|
||||||
|
import io.smnp.data.enumeration.Pitch
|
||||||
|
import io.smnp.type.enumeration.DataType.*
|
||||||
|
import io.smnp.type.matcher.Matcher.Companion.ofType
|
||||||
|
import io.smnp.type.model.Value
|
||||||
|
|
||||||
|
class NoteConstructor : Function("Note") {
|
||||||
|
override fun define(new: FunctionDefinitionTool) {
|
||||||
|
new function simple(
|
||||||
|
ofType(STRING),
|
||||||
|
ofType(INT),
|
||||||
|
ofType(INT),
|
||||||
|
ofType(BOOL)
|
||||||
|
) body { _, (pitchString, octave, duration, dot) ->
|
||||||
|
val pitch = Pitch.parse((pitchString.value as String).toLowerCase())
|
||||||
|
val note = Note(pitch, octave.value as Int, duration.value as Int, dot.value as Boolean)
|
||||||
|
Value.note(note)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
modules/math/build.gradle
Normal file
0
modules/math/build.gradle
Normal file
7
modules/math/gradle.properties
Normal file
7
modules/math/gradle.properties
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version=0.0.1
|
||||||
|
|
||||||
|
pluginVersion=0.1
|
||||||
|
pluginId=smnp.math
|
||||||
|
pluginClass=
|
||||||
|
pluginProvider=Bartłomiej Pluta
|
||||||
|
pluginDependencies=
|
||||||
10
modules/math/src/main/kotlin/io/smnp/ext/MathModule.kt
Normal file
10
modules/math/src/main/kotlin/io/smnp/ext/MathModule.kt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package io.smnp.ext
|
||||||
|
|
||||||
|
import io.smnp.ext.function.ModuloFunction
|
||||||
|
import io.smnp.ext.function.RangeFunction
|
||||||
|
import org.pf4j.Extension
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
class MathModule : NativeModuleProvider("smnp.math") {
|
||||||
|
override fun functions() = listOf(ModuloFunction(), RangeFunction())
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package io.smnp.ext.function
|
||||||
|
|
||||||
|
import io.smnp.callable.function.Function
|
||||||
|
import io.smnp.callable.function.FunctionDefinitionTool
|
||||||
|
import io.smnp.callable.signature.Signature.Companion.simple
|
||||||
|
import io.smnp.type.enumeration.DataType.INT
|
||||||
|
import io.smnp.type.matcher.Matcher.Companion.ofType
|
||||||
|
import io.smnp.type.model.Value
|
||||||
|
|
||||||
|
class ModuloFunction : Function("mod") {
|
||||||
|
override fun define(new: FunctionDefinitionTool) {
|
||||||
|
new function simple(ofType(INT), ofType(INT)) body { _, (a, b) ->
|
||||||
|
Value.int(a.value as Int % b.value as Int)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package io.smnp.ext.function
|
||||||
|
|
||||||
|
import io.smnp.callable.function.Function
|
||||||
|
import io.smnp.callable.function.FunctionDefinitionTool
|
||||||
|
import io.smnp.callable.signature.Signature.Companion.simple
|
||||||
|
import io.smnp.type.enumeration.DataType.INT
|
||||||
|
import io.smnp.type.matcher.Matcher.Companion.ofType
|
||||||
|
import io.smnp.type.model.Value
|
||||||
|
|
||||||
|
class RangeFunction : Function("range") {
|
||||||
|
override fun define(new: FunctionDefinitionTool) {
|
||||||
|
new function simple(ofType(INT), ofType(INT)) body { _, (begin, end) ->
|
||||||
|
Value.list(IntRange(begin.value as Int, end.value as Int).map { Value.int(it) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
modules/music/build.gradle
Normal file
0
modules/music/build.gradle
Normal file
7
modules/music/gradle.properties
Normal file
7
modules/music/gradle.properties
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version=0.0.1
|
||||||
|
|
||||||
|
pluginVersion=0.1
|
||||||
|
pluginId=smnp.music
|
||||||
|
pluginClass=
|
||||||
|
pluginProvider=Bartłomiej Pluta
|
||||||
|
pluginDependencies=
|
||||||
8
modules/music/src/main/kotlin/io/smnp/ext/MusicModule.kt
Normal file
8
modules/music/src/main/kotlin/io/smnp/ext/MusicModule.kt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package io.smnp.ext
|
||||||
|
|
||||||
|
import org.pf4j.Extension
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
class MusicModule : LanguageModuleProvider("smnp.music") {
|
||||||
|
override fun dependencies() = listOf("smnp.lang", "smnp.collection", "smnp.math")
|
||||||
|
}
|
||||||
105
modules/music/src/main/resources/main.mus
Normal file
105
modules/music/src/main/resources/main.mus
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
extend note as this {
|
||||||
|
function withOctave(octave: int) {
|
||||||
|
return Note(this.pitch, octave, this.duration, this.dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
function withDuration(duration: int) {
|
||||||
|
return Note(this.pitch, this.octave, duration, this.dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
function withDot(dot: bool) {
|
||||||
|
return Note(this.pitch, this.octave, this.duration, dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transpose(value: int) {
|
||||||
|
return noteFromInt(this.toInt() + value, this.duration, this.dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toInt() {
|
||||||
|
return this.octave * 12 + [
|
||||||
|
"C",
|
||||||
|
"C#",
|
||||||
|
"D",
|
||||||
|
"D#",
|
||||||
|
"E",
|
||||||
|
"F",
|
||||||
|
"F#",
|
||||||
|
"G",
|
||||||
|
"G#",
|
||||||
|
"A",
|
||||||
|
"A#",
|
||||||
|
"H"
|
||||||
|
].indexOf(this.pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function noteFromInt(intPitch: int, duration: int, dot: bool) {
|
||||||
|
pitch = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "H"].get(mod(intPitch, 12));
|
||||||
|
octave = Int(intPitch / 12);
|
||||||
|
return Note(pitch, octave, duration, dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
function range(begin: note, end: note, filter: string = "all", duration: int = 4, dot: bool = false) {
|
||||||
|
filters = {
|
||||||
|
"all" -> ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "H"],
|
||||||
|
"diatonic" -> ["C", "D", "E", "F", "G", "A", "H"],
|
||||||
|
"chromatic" -> ["C#", "D#", "F#", "G#", "A#"]
|
||||||
|
};
|
||||||
|
|
||||||
|
if(not filters.containsKey(filter)) {
|
||||||
|
throw "Unknown filter '" + filter + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFilter = filters.get(filter);
|
||||||
|
|
||||||
|
return (range(begin.toInt(), end.toInt()) as i ^ noteFromInt(i, duration, dot)) as n ^ n % currentFilter.contains(n.pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transpose(value: int, ...notes: <note, int, string>) {
|
||||||
|
return transpose(value, notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transpose(value: int, notes: list<note, int, string>) {
|
||||||
|
output = [];
|
||||||
|
notes as item ^ {
|
||||||
|
if(typeOf(item) == "note") {
|
||||||
|
output = output + [item.transpose(value)];
|
||||||
|
} else {
|
||||||
|
output = output + [item];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function semitones(...notes: <note, int, string>) {
|
||||||
|
return semitones(notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function semitones(staff: list<note, int, string>) {
|
||||||
|
notes = _filterNotes(staff);
|
||||||
|
if(notes.size < 2) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((notes.size - 1) as i ^ [notes.get(i+1).toInt() - notes.get(i).toInt()]).flatten();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _filterNotes(staff: list<note, int, string>) {
|
||||||
|
return staff as item ^ item % typeOf(item) == "note";
|
||||||
|
}
|
||||||
|
|
||||||
|
function transposeTo(target: note, ...notes: <note, int, string>) {
|
||||||
|
return transposeTo(target, notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function transposeTo(target: note, staff: list<note, int, string>) {
|
||||||
|
notes = _filterNotes(staff);
|
||||||
|
if(notes.size < 1) {
|
||||||
|
return staff;
|
||||||
|
}
|
||||||
|
|
||||||
|
semitones = semitones(notes.get(0), target).get(0);
|
||||||
|
|
||||||
|
return transpose(semitones, staff);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user