package akin.lang;
import java.io.*;
import java.awt.*;
import javax.swing.JPanel;
/**
Bootstrapper.run() is called to initialize the runtime.
Core classes are created and methods are added.
*/
public class Bootstrapper {
static public Context run() {
// Create core classes
AkinClass objectClass = new AkinClass("Object");
AkinRuntime.objectClass = objectClass;
// Each method sent or added on the root context of a script are evaled on the main object.
AkinObject main = new AkinObject();
AkinRuntime.mainObject = main;
AkinClass classClass = new AkinClass("Class");
objectClass.setAkinClass(classClass); // Object is a class
classClass.setAkinClass(classClass); // Class is a class
main.setAkinClass(objectClass);
// Register core classes into the root context
objectClass.setConstant("Object", objectClass);
objectClass.setConstant("Class", classClass);
// There is just one instance of nil, true, false, so we store those in constants.
AkinRuntime.nilObject = objectClass.newSubclass("NilClass").newInstance(null);
AkinRuntime.trueObject = objectClass.newSubclass("TrueClass").newInstance(true);
AkinRuntime.falseObject = objectClass.newSubclass("FalseClass").newInstance(false);
AkinClass stringClass = objectClass.newSubclass("String");
AkinClass numberClass = objectClass.newSubclass("Number");
AkinClass integerClass = numberClass.newSubclass("Integer");
AkinClass floatClass = numberClass.newSubclass("Float");
AkinClass arrayClass = objectClass.newSubclass("Array");
AkinClass exceptionClass = objectClass.newSubclass("Exception");
exceptionClass.newSubclass("IOException");
exceptionClass.newSubclass("TypeError");
exceptionClass.newSubclass("MethodNotFound");
exceptionClass.newSubclass("ArgumentError");
exceptionClass.newSubclass("FileNotFound");
// Add methods to core classes.
//// Object
objectClass.addMethod("print", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
for (AkinObject arg : arguments) System.out.println(arg.toJavaObject());
return AkinRuntime.getNil();
}
});
objectClass.addMethod("Print", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
for (AkinObject arg : arguments) System.out.println(arg.toJavaObject());
return AkinRuntime.getNil();
}
});
objectClass.addMethod("write", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
for (AkinObject arg : arguments) System.out.println(arg.toJavaObject());
return AkinRuntime.getNil();
}
});
objectClass.addMethod("Write", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
for (AkinObject arg : arguments) System.out.println(arg.toJavaObject());
return AkinRuntime.getNil();
}
});
objectClass.addMethod("class", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
return receiver.getAkinClass();
}
});
objectClass.addMethod("eval", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
Context context = new Context(receiver);
String code = arguments[0].asString();
return context.eval(code);
}
});
objectClass.addMethod("require", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
Context context = new Context();
String filename = arguments[0].asString();
try {
return context.eval(new FileReader(filename));
} catch (FileNotFoundException e) {
throw new AkinException("FileNotFound", "File not found: " + filename);
}
}
});
objectClass.addMethod("usethefile", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
Context context = new Context();
String filename = arguments[0].asString();
try {
return context.eval(new FileReader(filename));
} catch (FileNotFoundException e) {
throw new AkinException("FileNotFound", "File not found: " + filename);
}
}
});
objectClass.addMethod("take_input", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
Console console = System.console();
String string = arguments[0].asString();
String s = console.readLine(string);
return new ValueObject(s);
}
});
objectClass.addMethod("input_of", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
Console console = System.console();
String string = arguments[0].asString();
String s = console.readLine(string);
return new ValueObject(s);
}
});
objectClass.addMethod("input", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
Console console = System.console();
String string = arguments[0].asString();
String s = console.readLine(string);
return new ValueObject(s);
}
});
objectClass.addMethod("random_number", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
int min = arguments[0].asInteger();
int max = arguments[1].asInteger();
int x = min + (int)(Math.random() * ((max - min) + 1));
return new ValueObject(x);
}
});
//// Class
classClass.addMethod("new", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
AkinClass self = (AkinClass) receiver;
AkinObject instance = self.newInstance();
if (self.hasMethod("initialize")) instance.call("initialize", arguments);
return instance;
}
});
classClass.addMethod("name", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
AkinClass self = (AkinClass) receiver;
return new ValueObject(self.getName());
}
});
classClass.addMethod("superclass", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
AkinClass self = (AkinClass) receiver;
return self.getSuperClass();
}
});
//// Exception
exceptionClass.addMethod("initialize", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
if (arguments.length == 1) receiver.setInstanceVariable("message", arguments[0]);
return AkinRuntime.getNil();
}
});
exceptionClass.addMethod("message", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
return receiver.getInstanceVariable("message");
}
});
objectClass.addMethod("raise!", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
String message = null;
if (receiver.hasInstanceVariable("message")) message = receiver.getInstanceVariable("message").asString();
throw new AkinException(receiver.getAkinClass(), message);
}
});
//// Integer
integerClass.addMethod("+", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return new ValueObject(receiver + argument);
}
});
integerClass.addMethod("-", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return new ValueObject(receiver - argument);
}
});
integerClass.addMethod("*", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return new ValueObject(receiver * argument);
}
});
integerClass.addMethod("/", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return new ValueObject(receiver / argument);
}
});
integerClass.addMethod("<", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver < argument);
}
});
integerClass.addMethod("is less than", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver < argument);
}
});
integerClass.addMethod(">", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver > argument);
}
});
integerClass.addMethod("is greater than", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver > argument);
}
});
integerClass.addMethod("<=", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver <= argument);
}
});
integerClass.addMethod("is less than or equal to", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver <= argument);
}
});
integerClass.addMethod(">=", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver >= argument);
}
});
integerClass.addMethod("is greater than or equal to", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver >= argument);
}
});
integerClass.addMethod("==", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver == argument);
}
});
integerClass.addMethod("is equal to", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver == argument);
}
});
integerClass.addMethod("is not equal to", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver != argument);
}
});
integerClass.addMethod("!=", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver != argument);
}
});
integerClass.addMethod("as_a_string", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
int x = receiver.asInteger();
int y = x + 0;
return new ValueObject(Integer.toString(y));
}
});
//// Float
floatClass.addMethod("+", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return new ValueObject(receiver + argument);
}
});
floatClass.addMethod("-", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return new ValueObject(receiver - argument);
}
});
floatClass.addMethod("*", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return new ValueObject(receiver * argument);
}
});
floatClass.addMethod("/", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return new ValueObject(receiver / argument);
}
});
floatClass.addMethod("<", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver < argument);
}
});
floatClass.addMethod("is less than", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver < argument);
}
});
floatClass.addMethod(">", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver > argument);
}
});
floatClass.addMethod("is greater than", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver > argument);
}
});
floatClass.addMethod("<=", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver <= argument);
}
});
floatClass.addMethod("is less than or equal to", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver <= argument);
}
});
floatClass.addMethod(">=", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver >= argument);
}
});
floatClass.addMethod("is greater than or equal to", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver >= argument);
}
});
floatClass.addMethod("==", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver == argument);
}
});
floatClass.addMethod("is equal to", new OperatorMethod<Float>() {
public AkinObject perform(Float receiver, Float argument) throws AkinException {
return AkinRuntime.toBoolean(receiver == argument);
}
});
floatClass.addMethod("is not equal to", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver != argument);
}
});
floatClass.addMethod("!=", new OperatorMethod<Integer>() {
public AkinObject perform(Integer receiver, Integer argument) throws AkinException {
return AkinRuntime.toBoolean(receiver != argument);
}
});
//// String
stringClass.addMethod("+", new OperatorMethod<String>() {
public AkinObject perform(String receiver, String argument) throws AkinException {
return new ValueObject(receiver + argument);
}
});
stringClass.addMethod("size", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
String self = receiver.asString();
return new ValueObject(self.length());
}
});
stringClass.addMethod("substring", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
String self = receiver.asString();
if (arguments.length == 0) throw new ArgumentError("substring", 1, 0);
int start = arguments[0].asInteger();
int end = self.length();
if (arguments.length > 1) end = arguments[1].asInteger();
return new ValueObject(self.substring(start, end));
}
});
stringClass.addMethod("as_a_string", new Method() {
public AkinObject call(AkinObject receiver, AkinObject arguments[]) throws AkinException {
String self = receiver.asString();
return new ValueObject(self);
}
});
// Return the root context on which everything will be evaled. By default, everything is evaled on the
// main object.
return new Context(main);
}
}