const {ecall, generateStackTrace, currentTask} = _getModule('vm')
export class Error {
construct(message) {
this.message = message
this.stack = generateStackTrace(1)
this.task = currentTask()
}
toString() {
return 'In \(this.task): \(this.getClass().name()): \(this.message)\n\(this.stack)'
}
}
export class OverflowError extends Error {
construct(message) {
super.construct(message)
}
}
export class TypeError extends Error {
construct(message) {
super.construct(message)
}
}
export class ArgumentError extends Error {
construct(message) {
super.construct(message)
}
}
export class PropertyError extends Error {
construct(message) {
super.construct(message)
}
}
export class NoMethodError extends Error {
construct(message) {
super.construct(message)
}
}
export class NoModuleVariableError extends Error {
construct(message) {
super.construct(message)
}
}
export class IndexError extends Error {
construct(message) {
super.construct(message)
}
}
export class KeyError extends Error {
construct(message) {
super.construct(message)
}
}
export class CompileError extends Error {
construct(message) {
super.construct(message)
}
}
export class EFuncError extends Error{
construct(message) {
super.construct(message)
}
}
export class ModuleNotFoundError extends Error{
construct(message) {
super.construct(message)
}
}
export class DeadlockError extends Error{
construct(message) {
super.construct(message)
}
}
export fun import(moduleName) {
if moduleName.getClass() !== String {
throw new TypeError('The first argument must be a String, not \(moduleName.getClass().name())')
}
let module = _getModule(moduleName)
if module {
return module
}else {
moduleName = ecall(@resolveModule,{callerModule: _getCallerModule(), moduleName})
module = _getModule(moduleName)
if module {
return module
} else {
let source = ecall(@fetchModule, moduleName)
ecall(@compile, {moduleName, eval: false, source})()
return _getModule(moduleName)
}
}
}
export fun eval(source) {
if source.getClass() !== String {
throw new TypeError('The first argument must be a String, not \(source.getClass().name())')
}
let {function,isExpr} = ecall(@compile, {moduleName: _getCallerModule(), eval: true, source})
if(isExpr){
return function()
}else{
function()
return null
}
}
export fun exec(source) {
if source.getClass() !== String {
throw new TypeError('The first argument must be a String, not \(source.getClass().name())')
}
ecall(@compile, {moduleName: _getCallerModule(), eval: false, source})()
}
export class Iterator {
each(f) {
for elem in this {
f(elem)
}
}
all(f) {
for elem in this {
if !f(elem) {
return false
}
}
return true
}
any(f) {
for elem in this {
if f(elem) {
return true
}
}
return false
}
map(f) {
return new IteratorMap(this, f)
}
filter(f) {
return new IteratorFilter(this, f)
}
collect() {
let a = []
for elem in this {
a.push(elem)
}
return a
}
count() {
let count = 0
for _ in this {
count+=1
}
return count
}
reduce(f, initial) {
for elem in this {
initial = f(initial, elem)
}
return initial
}
}
class IteratorMap extends Iterator {
construct(iter, f) {
this._iter = iter
this._f = f
}
hasNext() {
return this._iter.hasNext()
}
next() {
return this._f(this._iter.next())
}
}
class IteratorFilter extends Iterator {
construct(iter, f) {
this._iter = iter
this._f = f
this._nextObject = null
this._nextObjectSet = false
}
hasNext() {
return this._nextObjectSet or this._setNextObject()
}
next() {
if !this._nextObjectSet and !this._setNextObject(){
return null
}
this._nextObjectSet = false
return this._nextObject
}
_setNextObject(){
while this._iter.hasNext(){
let obj = this._iter.next()
if this._f(obj){
this._nextObject = obj
this._nextObjectSet = true
return true
}
}
return false
}
}
_extendClass(ArrayIterator, Iterator)
_extendClass(MapIterator, Iterator)
_extendClass(StringIterator, Iterator)
_extendClass(Range, Iterator)
class ArraySort {
_partition(low, high, comp) {
let i = low - 1
let pivot = this[high]
for j in low..high {
if comp(this[j], pivot) {
i += 1
let t = this[i]
this[i] = this[j]
this[j] = t
}
}
let t = this[i+1]
this[i+1] = this[high]
this[high] = t
return i+1
}
_quickSort(low, high, comp) {
if low < high {
let pivot = this._partition(low, high, comp)
this._quickSort(low, pivot - 1, comp)
this._quickSort(pivot + 1, high, comp)
}
}
sort(f) {
this._quickSort(0, this.len()-1, f)
}
}
_copyMethods(Array, ArraySort)
export fun join(tasks) {
if tasks.getClass() != Array {
throw new TypeError('The first argument must be a list of tasks')
}
for task in tasks.iter() {
if task.getClass() != Task {
throw new TypeError('The first argument must be a list of tasks')
}
}
let monitorChan = new Channel()
for task in tasks.iter() {
task.monitor(monitorChan)
}
for i in 0..tasks.len() {
let task = monitorChan.recv()
if task.status() === @killed {
let reason = task.getUncaughtException()
for task in tasks {
task.kill(reason)
}
break
}
}
}