diff --git a/modules/collection/src/main/resources/list.mus b/modules/collection/src/main/resources/list.mus index d31b693..d691623 100644 --- a/modules/collection/src/main/resources/list.mus +++ b/modules/collection/src/main/resources/list.mus @@ -15,7 +15,7 @@ function _flatten(list: list, output: list) { } extend list as this { - function toFlat() { + function flatten() { return flatten(this); } @@ -23,6 +23,16 @@ extend list as this { 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 = ", ") { output = "" this as (item, index) ^ { diff --git a/modules/lang/src/main/kotlin/io/smnp/ext/lang/LangModule.kt b/modules/lang/src/main/kotlin/io/smnp/ext/lang/LangModule.kt index 8d66a33..5427330 100644 --- a/modules/lang/src/main/kotlin/io/smnp/ext/lang/LangModule.kt +++ b/modules/lang/src/main/kotlin/io/smnp/ext/lang/LangModule.kt @@ -1,6 +1,8 @@ package io.smnp.ext.lang 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.method.CharAtMethod import io.smnp.ext.lang.method.ListAccessMethod @@ -9,6 +11,6 @@ import org.pf4j.Extension @Extension class LangModule : NativeModuleProvider("smnp.lang") { - override fun functions() = listOf(TypeOfFunction()) + override fun functions() = listOf(IntConstructor(), NoteConstructor(), TypeOfFunction()) override fun methods() = listOf(ListAccessMethod(), MapAccessMethod(), CharAtMethod()) } \ No newline at end of file diff --git a/modules/lang/src/main/kotlin/io/smnp/ext/lang/constructor/IntConstructor.kt b/modules/lang/src/main/kotlin/io/smnp/ext/lang/constructor/IntConstructor.kt new file mode 100644 index 0000000..37593eb --- /dev/null +++ b/modules/lang/src/main/kotlin/io/smnp/ext/lang/constructor/IntConstructor.kt @@ -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()) + } + } +} \ No newline at end of file diff --git a/modules/lang/src/main/kotlin/io/smnp/ext/lang/constructor/NoteConstructor.kt b/modules/lang/src/main/kotlin/io/smnp/ext/lang/constructor/NoteConstructor.kt new file mode 100644 index 0000000..24b3a23 --- /dev/null +++ b/modules/lang/src/main/kotlin/io/smnp/ext/lang/constructor/NoteConstructor.kt @@ -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) + } + } +} \ No newline at end of file diff --git a/modules/math/build.gradle b/modules/math/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/modules/math/gradle.properties b/modules/math/gradle.properties new file mode 100644 index 0000000..eeab9d1 --- /dev/null +++ b/modules/math/gradle.properties @@ -0,0 +1,7 @@ +version=0.0.1 + +pluginVersion=0.1 +pluginId=smnp.math +pluginClass= +pluginProvider=Bartłomiej Pluta +pluginDependencies= \ No newline at end of file diff --git a/modules/math/src/main/kotlin/io/smnp/ext/MathModule.kt b/modules/math/src/main/kotlin/io/smnp/ext/MathModule.kt new file mode 100644 index 0000000..19eb421 --- /dev/null +++ b/modules/math/src/main/kotlin/io/smnp/ext/MathModule.kt @@ -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()) +} \ No newline at end of file diff --git a/modules/math/src/main/kotlin/io/smnp/ext/function/ModuloFunction.kt b/modules/math/src/main/kotlin/io/smnp/ext/function/ModuloFunction.kt new file mode 100644 index 0000000..e2ab4bd --- /dev/null +++ b/modules/math/src/main/kotlin/io/smnp/ext/function/ModuloFunction.kt @@ -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) + } + } +} \ No newline at end of file diff --git a/modules/math/src/main/kotlin/io/smnp/ext/function/RangeFunction.kt b/modules/math/src/main/kotlin/io/smnp/ext/function/RangeFunction.kt new file mode 100644 index 0000000..92cc9f7 --- /dev/null +++ b/modules/math/src/main/kotlin/io/smnp/ext/function/RangeFunction.kt @@ -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) }) + } + } +} \ No newline at end of file diff --git a/modules/music/build.gradle b/modules/music/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/modules/music/gradle.properties b/modules/music/gradle.properties new file mode 100644 index 0000000..9725a0a --- /dev/null +++ b/modules/music/gradle.properties @@ -0,0 +1,7 @@ +version=0.0.1 + +pluginVersion=0.1 +pluginId=smnp.music +pluginClass= +pluginProvider=Bartłomiej Pluta +pluginDependencies= \ No newline at end of file diff --git a/modules/music/src/main/kotlin/io/smnp/ext/MusicModule.kt b/modules/music/src/main/kotlin/io/smnp/ext/MusicModule.kt new file mode 100644 index 0000000..02fa578 --- /dev/null +++ b/modules/music/src/main/kotlin/io/smnp/ext/MusicModule.kt @@ -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") +} \ No newline at end of file diff --git a/modules/music/src/main/resources/main.mus b/modules/music/src/main/resources/main.mus new file mode 100644 index 0000000..7dca5a9 --- /dev/null +++ b/modules/music/src/main/resources/main.mus @@ -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: ) { + return transpose(value, notes); +} + +function transpose(value: int, notes: list) { + output = []; + notes as item ^ { + if(typeOf(item) == "note") { + output = output + [item.transpose(value)]; + } else { + output = output + [item]; + } + } + + return output; +} + +function semitones(...notes: ) { + return semitones(notes); +} + +function semitones(staff: list) { + 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) { + return staff as item ^ item % typeOf(item) == "note"; +} + +function transposeTo(target: note, ...notes: ) { + return transposeTo(target, notes); +} + +function transposeTo(target: note, staff: list) { + notes = _filterNotes(staff); + if(notes.size < 1) { + return staff; + } + + semitones = semitones(notes.get(0), target).get(0); + + return transpose(semitones, staff); +} \ No newline at end of file