Compare commits
17 Commits
1db1b01b2a
...
master
Author | SHA1 | Date | |
---|---|---|---|
235910b863 | |||
33cb150cf0 | |||
66fe79f2bf | |||
d75b000ad1 | |||
22d00d0360 | |||
8da76b5a3f | |||
ee48ec29f0 | |||
6efcea643f | |||
7fbab0e2a0 | |||
ee5c032d90 | |||
ea5d318b62 | |||
81a483d540 | |||
004db89c60 | |||
a786e9441c | |||
97cc99146b | |||
6369d15e93 | |||
acded68da5 |
14
carp/src/Pipfile
Normal file
14
carp/src/Pipfile
Normal file
@@ -0,0 +1,14 @@
|
||||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[packages]
|
||||
flask = "*"
|
||||
requests = "*"
|
||||
msgpack = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3"
|
0
carp/src/bridge/__init__.py
Normal file
0
carp/src/bridge/__init__.py
Normal file
179
carp/src/bridge/bridge.py
Normal file
179
carp/src/bridge/bridge.py
Normal file
@@ -0,0 +1,179 @@
|
||||
import argparse
|
||||
import threading
|
||||
import sys
|
||||
from bridge import carp
|
||||
from bridge.hooks import *
|
||||
from bridge.object_registry import registry
|
||||
|
||||
def pbbreak():
|
||||
print("Breaking now")
|
||||
breakpoint()
|
||||
print("Continuing")
|
||||
|
||||
|
||||
class EvalCommand:
|
||||
statements = ""
|
||||
bindings = {}
|
||||
commandId = 0
|
||||
|
||||
def __init__(self, commandId, statements, bindings):
|
||||
self.statements = statements
|
||||
self.commandId = commandId
|
||||
self.bindings = bindings
|
||||
|
||||
def execute_using_env(self, env):
|
||||
try:
|
||||
return self.execute()
|
||||
except Exception as err:
|
||||
self.perform_proceed_action(notify_error(err,self))
|
||||
|
||||
def perform_proceed_action(self, actionDict):
|
||||
actionSymbol = actionDict['action']
|
||||
if actionSymbol == "IGNORE":
|
||||
pass
|
||||
if actionSymbol == "DROP_QUEUE":
|
||||
bridge.globals.globalCommandList.drop_queue()
|
||||
if actionSymbol == "REPLACE_COMMAND":
|
||||
commandDict = actionDict["command"]
|
||||
bridge.globals.globalCommandList.push_command_at_first(EvalCommand(
|
||||
commandDict["commandId"],
|
||||
commandDict["statements"],
|
||||
commandDict["bindings"]))
|
||||
|
||||
def command_id(self):
|
||||
return self.commandId
|
||||
|
||||
def execute(self):
|
||||
return bridge.globals.proc.evaluate(self.statements)
|
||||
|
||||
class Logger():
|
||||
def log(self, msg):
|
||||
print(str(msg), file=sys.stderr, flush=True)
|
||||
|
||||
class NoLogger():
|
||||
def log(self, msg):
|
||||
pass
|
||||
|
||||
# This List is thought to be multi-producer and single-consumer. For optimal results wait for push_command return value to push another command that depends on the previous one.
|
||||
class CommandList:
|
||||
currentCommandIndex = 0
|
||||
commandList = []
|
||||
listLock = threading.Lock()
|
||||
consumeSemaphore = threading.Semaphore(value=0)
|
||||
|
||||
# This method locks the thread until the command has been succesfully appended to the list. Even though that it has a lock inside, we do not expect long waiting time.
|
||||
def push_command(self, aCommand):
|
||||
self.listLock.acquire()
|
||||
self.commandList.append(aCommand)
|
||||
commandIndex = len(self.commandList) - 1
|
||||
self.listLock.release()
|
||||
self.consumeSemaphore.release()
|
||||
return commandIndex
|
||||
|
||||
def push_command_at_first(self, aCommand):
|
||||
self.listLock.acquire()
|
||||
self.commandList.insert(self.currentCommandIndex, aCommand)
|
||||
self.listLock.release()
|
||||
self.consumeSemaphore.release()
|
||||
return self.currentCommandIndex
|
||||
|
||||
def drop_queue(self):
|
||||
self.listLock.acquire()
|
||||
self.consumeSemaphore = threading.Semaphore(value=0)
|
||||
self.currentCommandIndex = len(self.commandList)
|
||||
self.listLock.release()
|
||||
|
||||
def consume_command(self):
|
||||
repeatMonitorFlag = True
|
||||
while repeatMonitorFlag:
|
||||
self.consumeSemaphore.acquire()
|
||||
self.listLock.acquire()
|
||||
repeatMonitorFlag = False
|
||||
if(self.currentCommandIndex >= len(self.commandList)):
|
||||
repeatMonitorFlag = True
|
||||
self.listLock.release()
|
||||
command = self.commandList[self.currentCommandIndex]
|
||||
self.currentCommandIndex += 1
|
||||
self.listLock.release()
|
||||
return command
|
||||
|
||||
def get_current_command(self):
|
||||
if self.currentCommandIndex == 0:
|
||||
return None
|
||||
self.listLock.acquire()
|
||||
command = self.commandList[self.currentCommandIndex-1]
|
||||
self.listLock.release()
|
||||
return command
|
||||
|
||||
def get_command_list(self):
|
||||
self.listLock.acquire()
|
||||
listCopy = self.commandList.copy()
|
||||
self.listLock.release()
|
||||
return listCopy
|
||||
|
||||
#### UTILS FUNCTIONS
|
||||
def clean_locals_env():
|
||||
return locals()
|
||||
|
||||
def deserialize(text):
|
||||
result = bridge.globals.msg_service.serializer.deserialize(text)
|
||||
bridge.globals.logger.log("DESERIALISE (bridge): " + str(result))
|
||||
if registry().isProxy(result):
|
||||
result = registry().resolve(result['__pyid__'])
|
||||
return result
|
||||
|
||||
def enqueue_command(data):
|
||||
bridge.globals.globalCommandList.push_command(EvalCommand(
|
||||
data["commandId"],
|
||||
data["statements"],
|
||||
{k: deserialize(v) for k, v in data["bindings"].items()}))
|
||||
|
||||
def run_bridge():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("-p", "--port", required=False,
|
||||
help="port to be used for receiving instructions")
|
||||
ap.add_argument("-o", "--pharo", required=True,
|
||||
help="port to be used for sending notifications back to pharo")
|
||||
ap.add_argument("-m", "--method", required=False,
|
||||
help="identifier for communication protocol strategy http or msgpack")
|
||||
ap.add_argument("--log", required=False, const=True, nargs="?",
|
||||
help="enable logging")
|
||||
args = vars(ap.parse_args())
|
||||
|
||||
bridge.globals.proc = carp.start_carp_proc()
|
||||
bridge.globals.pharoPort = args["pharo"]
|
||||
if args["log"]:
|
||||
bridge.globals.logger = Logger()
|
||||
else:
|
||||
bridge.globals.logger = NoLogger()
|
||||
bridge.globals.pyPort = args["port"]
|
||||
bridge.globals.globalCommandList = CommandList()
|
||||
globalCommandList = bridge.globals.globalCommandList
|
||||
env = clean_locals_env()
|
||||
msg_service = None
|
||||
if args["port"] == None:
|
||||
args["port"] = '0'
|
||||
if args["method"] == None:
|
||||
args["method"] = 'http'
|
||||
if args["method"] == 'http':
|
||||
from bridge import flask_platform
|
||||
msg_service = flask_platform.build_service(int(args["port"]), int(args["pharo"]), enqueue_command)
|
||||
elif args["method"] == 'msgpack':
|
||||
from bridge import msgpack_socket_platform
|
||||
msg_service = msgpack_socket_platform.build_service(int(args["port"]), int(args["pharo"]), enqueue_command)
|
||||
else:
|
||||
raise Exception("Invalid communication strategy.")
|
||||
bridge.globals.msg_service = msg_service
|
||||
msg_service.start()
|
||||
bridge.globals.logger.log("CARP: Carp version " + bridge.globals.proc.version_info())
|
||||
bridge.globals.logger.log("CARP: Start consuming commands")
|
||||
while True:
|
||||
command = globalCommandList.consume_command()
|
||||
bridge.globals.logger.log("CARP: Executing command " + command.command_id())
|
||||
bridge.globals.logger.log("CARP: bindings: " + str(command.bindings))
|
||||
bridge.globals.logger.log("CARP: " + command.statements)
|
||||
notify(command.execute_using_env(env), command.command_id())
|
||||
bridge.globals.logger.log("CARP: Finished command execution")
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_bridge()
|
47
carp/src/bridge/carp.py
Normal file
47
carp/src/bridge/carp.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import re
|
||||
import time
|
||||
import diplomat
|
||||
|
||||
|
||||
class CarpProc:
|
||||
def __init__(self):
|
||||
self.proc = diplomat.Diplomat('carp')
|
||||
self._version_info = None
|
||||
self.adornment_re = re.compile(".\[33m.*?\[0m")
|
||||
self.warning_re = re.compile("\[WARNING\] (.*)\n?")
|
||||
|
||||
def wait_for_boot(self):
|
||||
while not self.proc.output():
|
||||
time.sleep(0.5)
|
||||
return self
|
||||
|
||||
def version_info(self):
|
||||
if not self._version_info:
|
||||
self._version_info = list(self.proc.output_stream())[0].replace("Welcome to Carp ", "")[:-1]
|
||||
return self._version_info
|
||||
|
||||
def read_output(self, old_output):
|
||||
while self.proc.output() == old_output:
|
||||
time.sleep(0.5)
|
||||
res = self.adornment_re.sub("", self.proc.output()[len(old_output):]).strip()
|
||||
warnings = self.warning_re.findall(res)
|
||||
res = self.warning_re.sub("", res)
|
||||
if res.startswith("=> "):
|
||||
return {'result': 'success', 'value': res[3:], 'warnings': warnings}
|
||||
if not res:
|
||||
return {'result': 'success', 'value': '()', 'warnings': warnings}
|
||||
return {'result': 'error', 'value': res, 'warnings': warnings}
|
||||
|
||||
def evaluate(self, statements):
|
||||
assert self.proc.is_running(), "carp process has died"
|
||||
if not self._version_info:
|
||||
self.version_info()
|
||||
|
||||
old_output = self.proc.output()
|
||||
self.proc._process.stdin.write(statements.encode("utf-8") + b"\n")
|
||||
self.proc._process.stdin.flush()
|
||||
return self.read_output(old_output)
|
||||
|
||||
|
||||
def start_carp_proc():
|
||||
return CarpProc().wait_for_boot()
|
73
carp/src/bridge/flask_platform.py
Normal file
73
carp/src/bridge/flask_platform.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from flask import Flask, request
|
||||
import http.client
|
||||
import json
|
||||
import threading
|
||||
import bridge.globals
|
||||
import bridge.utils
|
||||
from bridge import json_encoder
|
||||
import sys
|
||||
import logging
|
||||
import requests
|
||||
|
||||
class FlaskMsgService:
|
||||
|
||||
def __init__(self, port, pharo_port, feed_callback):
|
||||
self.serializer = json_encoder.JsonSerializer()
|
||||
log = logging.getLogger('werkzeug')
|
||||
log.setLevel(logging.ERROR)
|
||||
self.thread = None
|
||||
self.port = port
|
||||
self.pharo_port = pharo_port
|
||||
self.feed_callback = feed_callback
|
||||
self.app = Flask('carp_bridge')
|
||||
self.app.use_reloader=False
|
||||
self.session = requests.Session()
|
||||
self.session.trust_env = True
|
||||
|
||||
@self.app.route("/ENQUEUE", methods=["POST"])
|
||||
def eval_expression():
|
||||
data = request.get_json(force=True)
|
||||
self.feed_callback(data)
|
||||
return "{}"
|
||||
|
||||
@self.app.route("/IS_ALIVE", methods=["POST"])
|
||||
def status_endpoint():
|
||||
return "{}"
|
||||
|
||||
def addMapping(self, key_type, mapping_function):
|
||||
json_encoder.addMapping(key_type, mapping_function)
|
||||
|
||||
def _start(self):
|
||||
try:
|
||||
self.app.run(port=self.port)
|
||||
except OSError as err:
|
||||
bridge.globals.logger.log('Critical Error:' + str(err))
|
||||
exit(42)
|
||||
|
||||
def start(self):
|
||||
self.thread = threading.Thread(target=self._start, args=())
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
|
||||
def is_running(self):
|
||||
return self.thread != None
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
def send_async_message(self, msg):
|
||||
self.send_sync_message(msg)
|
||||
|
||||
def send_sync_message(self, msg):
|
||||
msg['__sync'] = bridge.utils.random_str()
|
||||
bridge.globals.logger.log("SYNC_MSG: " + json.dumps(msg))
|
||||
response = self.session.post(
|
||||
'http://localhost:' + str(self.pharo_port) + '/' + msg['type'],
|
||||
data=json.dumps(msg),
|
||||
headers={'content-type': 'application/json'},
|
||||
allow_redirects=True).content.decode('utf-8')
|
||||
bridge.globals.logger.log("SYNC_ANS: " + response)
|
||||
return json.loads(response)
|
||||
|
||||
def build_service(port, pharo_port, feed_callback):
|
||||
return FlaskMsgService(port, pharo_port, feed_callback)
|
0
carp/src/bridge/globals.py
Normal file
0
carp/src/bridge/globals.py
Normal file
50
carp/src/bridge/hooks.py
Normal file
50
carp/src/bridge/hooks.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from flask import Flask, request
|
||||
import http.client
|
||||
import argparse
|
||||
import sys
|
||||
import traceback
|
||||
import bridge.globals
|
||||
|
||||
def serialize(obj):
|
||||
return bridge.globals.msg_service.serializer.serialize(obj)
|
||||
|
||||
def deserialize(text):
|
||||
return bridge.globals.msg_service.serializer.deserialize(text)
|
||||
|
||||
def observer(commandId, observerId):
|
||||
return lambda obj: notify_observer(obj, commandId, observerId)
|
||||
|
||||
#### NOTIFICATION FUNCTIONS
|
||||
def notify(obj, notificationId):
|
||||
bridge.globals.logger.log("PYTHON: Notify " + str(notificationId))
|
||||
data = {}
|
||||
data["type"] = "EVAL"
|
||||
data["id"] = notificationId
|
||||
data["value"] = serialize(obj)
|
||||
bridge.globals.msg_service.send_async_message(data)
|
||||
|
||||
def notify_observer(obj, commandId, observerId):
|
||||
bridge.globals.logger.log("PYTHON: Notify observer " + str(commandId) + " " + str(observerId))
|
||||
data = {}
|
||||
data["type"] = "CALLBACK"
|
||||
data["commandId"] = commandId
|
||||
data["observerId"] = observerId
|
||||
data["value"] = serialize(obj)
|
||||
rawValue = bridge.globals.msg_service.send_sync_message(data)['value']
|
||||
return deserialize(rawValue)
|
||||
|
||||
def notify_error(ex, command):
|
||||
bridge.globals.logger.log("Error on command: " + str(command.command_id()))
|
||||
bridge.globals.logger.log("Exception: " + str(ex))
|
||||
data = {}
|
||||
data["type"] = "ERR"
|
||||
data["errMsg"] = str(ex)
|
||||
data["trace"] = traceback.format_exc(100)
|
||||
data["commandId"] = command.command_id()
|
||||
return bridge.globals.msg_service.send_sync_message(data)
|
||||
|
||||
def bridge_inspect(obj):
|
||||
if hasattr(obj,'__dict__'):
|
||||
return obj.__dict__
|
||||
else:
|
||||
return {}
|
28
carp/src/bridge/json_encoder.py
Normal file
28
carp/src/bridge/json_encoder.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import json
|
||||
import io
|
||||
from bridge.object_registry import registry
|
||||
|
||||
mapper = {}
|
||||
|
||||
def addMapping(key_type, mapping_function):
|
||||
mapper[key_type] = mapping_function
|
||||
|
||||
class JsonEncoder(json.JSONEncoder):
|
||||
def __init__(self, *args, **kwargs):
|
||||
json.JSONEncoder.__init__(self, *args, **kwargs)
|
||||
self.mapper = mapper
|
||||
|
||||
def default(self, obj):
|
||||
if type(obj) in self.mapper:
|
||||
return self.mapper[type(obj)](obj)
|
||||
return {
|
||||
'__pyclass__': type(obj).__name__,
|
||||
'__pyid__': registry().register(obj)
|
||||
}
|
||||
|
||||
class JsonSerializer:
|
||||
def serialize(self, obj):
|
||||
return json.dumps(obj, cls=JsonEncoder)
|
||||
|
||||
def deserialize(self, text):
|
||||
return json.loads(text)
|
41
carp/src/bridge/msgpack_serializer.py
Normal file
41
carp/src/bridge/msgpack_serializer.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import msgpack
|
||||
from bridge.object_registry import registry
|
||||
|
||||
primitive_types = [
|
||||
type(None),
|
||||
bool,
|
||||
int,
|
||||
bytes,
|
||||
str,
|
||||
dict,
|
||||
list,
|
||||
memoryview,
|
||||
bytearray]
|
||||
|
||||
mapper = {}
|
||||
|
||||
def addMapping(key_type, mapping_function):
|
||||
mapper[key_type] = mapping_function
|
||||
|
||||
class MsgPackSerializer:
|
||||
def __init__(self):
|
||||
self.primitive_types = primitive_types
|
||||
|
||||
def mapper(self):
|
||||
return mapper
|
||||
|
||||
def default(self, obj):
|
||||
if type(obj) in self.primitive_types:
|
||||
return obj
|
||||
if type(obj) in self.mapper():
|
||||
return self.mapper()[type(obj)](obj)
|
||||
return {
|
||||
'__pyclass__': type(obj).__name__,
|
||||
'__pyid__': registry().register(obj)
|
||||
}
|
||||
|
||||
def serialize(self, obj):
|
||||
return msgpack.packb(obj, default=self.default, use_bin_type=True)
|
||||
|
||||
def deserialize(self, binary):
|
||||
return msgpack.unpackb(binary, raw=False)
|
120
carp/src/bridge/msgpack_socket_platform.py
Normal file
120
carp/src/bridge/msgpack_socket_platform.py
Normal file
@@ -0,0 +1,120 @@
|
||||
import msgpack
|
||||
import socket
|
||||
import _thread
|
||||
import threading
|
||||
import time
|
||||
import sys
|
||||
import bridge.globals
|
||||
from bridge import stoppable_thread, msgpack_serializer
|
||||
from uuid import uuid1
|
||||
|
||||
# Messages supported by this sockets must be Dictionaries. This is because we use special key __sync to know if it is
|
||||
# a synchronized message or not. If it is we hook a semaphore to that id under the __sync key and after we receive the
|
||||
# value we store there the return message and signal the semaphore.
|
||||
class MsgPackSocketPlatform:
|
||||
|
||||
def __init__(self, port):
|
||||
self.port = port
|
||||
self.client = None
|
||||
self.serializer = msgpack_serializer.MsgPackSerializer()
|
||||
self.unpacker = msgpack.Unpacker(raw=False)
|
||||
self.packer = msgpack.Packer(use_bin_type=True)
|
||||
self.sync_table = {}
|
||||
self.async_handlers = {}
|
||||
|
||||
def addMapping(self, key_type, mapping_function):
|
||||
msgpack_serializer.addMapping(key_type, mapping_function)
|
||||
|
||||
def set_handler(self, msg_type, async_handler):
|
||||
self.async_handlers[msg_type] = async_handler
|
||||
|
||||
def prim_handle(self):
|
||||
try:
|
||||
bridge.globals.logger.log("loop func")
|
||||
data = self.client.recv(2048)
|
||||
if len(data) == 0:
|
||||
time.sleep(0.005)
|
||||
else:
|
||||
self.unpacker.feed(data)
|
||||
for msg in self.unpacker:
|
||||
bridge.globals.logger.log("prim handle message")
|
||||
self.prim_handle_msg(msg)
|
||||
except OSError:
|
||||
bridge.globals.logger.log("OSError: " + str(err))
|
||||
self.stop()
|
||||
sys.exit()
|
||||
exit(-1)
|
||||
except Exception as err:
|
||||
bridge.globals.logger.log("ERROR message: " + str(err))
|
||||
|
||||
def setup_func(self):
|
||||
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.client.connect(('localhost', self.port))
|
||||
|
||||
def stop(self):
|
||||
if self.thread is not None:
|
||||
self.thread.stop()
|
||||
if self.client is not None:
|
||||
self.client.close()
|
||||
self.client = None
|
||||
|
||||
def send_answer(self, msg, answer):
|
||||
if answer['type'] != msg['type']:
|
||||
raise Exception('Type mismatch')
|
||||
answer['__sync'] = msg['__sync']
|
||||
self.send_async_message(answer)
|
||||
|
||||
def is_running(self):
|
||||
return self.client != None
|
||||
|
||||
def prim_handle_msg(self, raw_msg):
|
||||
msg = raw_msg
|
||||
msg_type = msg['type']
|
||||
if msg_type in self.async_handlers:
|
||||
self.async_handlers[msg['type']](msg)
|
||||
elif is_sync_msg(msg):
|
||||
sync_id = message_sync_id(msg)
|
||||
semaphore = self.sync_table[sync_id]
|
||||
self.sync_table[sync_id] = msg
|
||||
semaphore.release()
|
||||
else:
|
||||
bridge.globals.logger.log("Error! Msg couldnt be handled")
|
||||
raise Exception('Message couldn''t be handled')
|
||||
|
||||
|
||||
def start(self):
|
||||
self.thread = stoppable_thread.StoppableThread(
|
||||
loop_func= self.prim_handle,
|
||||
setup_func= self.setup_func)
|
||||
self.thread.start()
|
||||
time.sleep(.1)
|
||||
|
||||
def send_async_message(self, msg):
|
||||
self.client.send(self.packer.pack(msg))
|
||||
|
||||
def send_sync_message(self, msg):
|
||||
sync_id = mark_message_as_sync(msg)
|
||||
semaphore = threading.Semaphore(value=0)
|
||||
self.sync_table[sync_id] = semaphore
|
||||
self.send_async_message(msg)
|
||||
semaphore.acquire()
|
||||
ans = self.sync_table[sync_id]
|
||||
del self.sync_table[sync_id]
|
||||
return ans
|
||||
|
||||
def is_sync_msg(msg):
|
||||
return '__sync' in msg
|
||||
|
||||
def message_sync_id(msg):
|
||||
return msg['__sync']
|
||||
|
||||
def mark_message_as_sync(msg):
|
||||
sync_id = uuid1().hex
|
||||
msg['__sync'] = sync_id
|
||||
return sync_id
|
||||
|
||||
def build_service(port, pharo_port, feed_callback):
|
||||
service = MsgPackSocketPlatform(pharo_port)
|
||||
service.set_handler('ENQUEUE',feed_callback)
|
||||
service.set_handler('IS_ALIVE', lambda msg: service.send_answer(msg, {'type': 'IS_ALIVE'}))
|
||||
return service
|
88
carp/src/bridge/object_registry.py
Normal file
88
carp/src/bridge/object_registry.py
Normal file
@@ -0,0 +1,88 @@
|
||||
import bridge.globals
|
||||
from uuid import uuid1
|
||||
|
||||
def ensure_global_registry():
|
||||
if not hasattr(bridge.globals, 'ObjectRegistry'):
|
||||
bridge.globals.ObjectRegistry = Registry()
|
||||
|
||||
def registry():
|
||||
return bridge.globals.ObjectRegistry
|
||||
|
||||
primitive = (int, str, bool)
|
||||
|
||||
def is_primitive(obj):
|
||||
return isinstance(obj, primitive)
|
||||
|
||||
class Registry():
|
||||
|
||||
def __init__(self):
|
||||
self.idToObjMap = {}
|
||||
self.objToIdMap = {}
|
||||
|
||||
def hasId(self, anId):
|
||||
return anId in self.idToObjMap
|
||||
|
||||
def createNewObjId(self):
|
||||
return uuid1().hex
|
||||
|
||||
def register(self, obj):
|
||||
if obj is None or is_primitive(obj):
|
||||
return 0
|
||||
if id(obj) in self.objToIdMap:
|
||||
return self.objToIdMap[id(obj)]
|
||||
else:
|
||||
return self._register(obj, self.createNewObjId())
|
||||
|
||||
def register_with_id(self, obj, newObjId):
|
||||
if obj is None or is_primitive(obj):
|
||||
return RegisterForbiddenObject(obj)
|
||||
if id(obj) in self.objToIdMap:
|
||||
objId = self.objToIdMap[id(obj)]
|
||||
if objId == newObjId:
|
||||
return newObjId
|
||||
else:
|
||||
raise RegisterWithDifferentIdError(obj, newObjId)
|
||||
else:
|
||||
return self._register(obj, newObjId)
|
||||
|
||||
def resolve(self, objId):
|
||||
if objId in self.idToObjMap:
|
||||
return self.idToObjMap[objId]
|
||||
else:
|
||||
raise ResolveUnknownObject(objId)
|
||||
|
||||
def _register(self, obj, newObjId):
|
||||
self.idToObjMap[newObjId] = obj
|
||||
self.objToIdMap[id(obj)] = newObjId
|
||||
return newObjId
|
||||
|
||||
def clean(self, objId):
|
||||
obj = self.idToObjMap[objId]
|
||||
del self.idToObjMap[objId]
|
||||
del self.objToIdMap[id(obj)]
|
||||
|
||||
def isProxy(self, anObject):
|
||||
is_proxy = False
|
||||
|
||||
if isinstance(anObject, dict):
|
||||
if len(anObject.keys()) == 2 and ('__pyclass__' in anObject) and ('__pyid__' in anObject):
|
||||
is_proxy = True
|
||||
|
||||
return is_proxy
|
||||
|
||||
class RegistryError(Exception):
|
||||
pass
|
||||
|
||||
class RegisterWithDifferentIdError(RegistryError):
|
||||
def __init__(self, obj, newId):
|
||||
RegistryError.__init__(self,"Attempting to register object {0} with ID {1} with different ID {2}.".format(type(obj).__name__, registry().register(obj), newId))
|
||||
|
||||
class ResolveUnknownObject(RegistryError):
|
||||
def __init__(self, objId):
|
||||
RegistryError.__init__(self,"Attempting to resolve unknown object with id {0}.".format(objId))
|
||||
|
||||
class RegisterForbiddenObject(RegistryError):
|
||||
def __init__(self, obj):
|
||||
RegistryError.__init__(self,"Attempting to register forbidden object of type {0}.".format(type(obj).__name__))
|
||||
|
||||
ensure_global_registry()
|
24
carp/src/bridge/stoppable_thread.py
Normal file
24
carp/src/bridge/stoppable_thread.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import threading
|
||||
|
||||
class StoppableThread(threading.Thread):
|
||||
def __init__(self, loop_func, setup_func):
|
||||
threading.Thread.__init__(self)
|
||||
self._stop_event = threading.Event()
|
||||
self.daemon = True
|
||||
self.loop_func = loop_func
|
||||
self.setup_func = setup_func
|
||||
|
||||
# function using _stop function
|
||||
def stop(self):
|
||||
self._stop_event.set()
|
||||
|
||||
def stopped(self):
|
||||
return self._stop_event.isSet()
|
||||
|
||||
def run(self):
|
||||
self.setup_func()
|
||||
while True:
|
||||
if self.stopped():
|
||||
return
|
||||
self.loop_func()
|
||||
|
36
carp/src/bridge/tfactorial.py
Normal file
36
carp/src/bridge/tfactorial.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import argparse
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
# Calculate the factorial
|
||||
def factorial(n, t):
|
||||
time.sleep(n*t/4)
|
||||
print("Start: " + str(t) + ": " + str(n))
|
||||
if n == 1:
|
||||
res = 1
|
||||
if t == 1:
|
||||
print("Feel free to break here")
|
||||
else:
|
||||
res = n * factorial(n-1, t)
|
||||
return res
|
||||
|
||||
|
||||
# Calculate the factorial and print the result
|
||||
def factorial_thread(n, t):
|
||||
time.sleep(2)
|
||||
result = factorial(n, t)
|
||||
print("Thread " + str(t) + " = "+str(result))
|
||||
|
||||
|
||||
def launch_factorials(n):
|
||||
threads = []
|
||||
print("Calculate: "+str(n))
|
||||
breakpoint()
|
||||
for i in range(n):
|
||||
threads.append(threading.Thread(target=factorial_thread, args=(n+i, i+1)))
|
||||
threads[-1].start()
|
||||
print("Wait for the results")
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
print("Done")
|
2
carp/src/bridge/tmp.py
Normal file
2
carp/src/bridge/tmp.py
Normal file
@@ -0,0 +1,2 @@
|
||||
import time
|
||||
time.sleep(3)
|
5
carp/src/bridge/utils.py
Normal file
5
carp/src/bridge/utils.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from uuid import uuid1
|
||||
|
||||
def random_str():
|
||||
return uuid1().hex
|
||||
|
17
carp/src/languagelink.carp
Normal file
17
carp/src/languagelink.carp
Normal file
@@ -0,0 +1,17 @@
|
||||
(load "/Users/veitheller/Documents/Code/Github/carp/archive/socket/sockets.carp")
|
||||
|
||||
(use Socket)
|
||||
|
||||
(defn main []
|
||||
(let-do [port (Maybe.from (from-string &(Maybe.from (nth &System.args 1) @"")) 0)]
|
||||
(IO.println &(fmt "Starting server on localhost, port %d" port))
|
||||
(Socket.with-server sock "127.0.0.1" port
|
||||
(if (Socket.valid? &sock)
|
||||
(Socket.while-connection &sock client
|
||||
(IO.println &(read &client))
|
||||
(send &client "hi")
|
||||
(IO.println "yay"))
|
||||
(IO.errorln "Server couldn’t be started.")))))
|
||||
|
||||
(build)
|
||||
(run)
|
4
carp/src/languagelink.py
Normal file
4
carp/src/languagelink.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from bridge import bridge as b
|
||||
from bridge.hooks import *
|
||||
|
||||
b.run_bridge()
|
@@ -8,7 +8,45 @@
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T22:22:31.801924+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T22:22:40.406467+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "3kLYI0GZDQCKnLdXBAU6hQ=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Interlude: An Introduction to Carp]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
@@ -41,43 +79,6 @@
|
||||
},
|
||||
"string" : "[[Introduction]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T22:22:30.537898+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T22:22:30.537898+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "3kLYI0GZDQCKnLdXBAU6hQ=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : ""
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
@@ -231,7 +232,119 @@
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:20.565513+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:20.565513+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "UXDVu4+dDQC/fqHFA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Building a LanguageLink client]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:33.223032+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:33.223032+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "6dWWvI+dDQC/gM7QA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Building a LanguageLink server]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:45.88618+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:48.608001+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "rYmTAZCdDQC/qIzPA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[What now?]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
@@ -264,6 +377,81 @@
|
||||
},
|
||||
"string" : "[[Executing code]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:07:50.665361+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:07:59.692968+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "3NNC/o+dDQC/oLtxA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Hooking up your LanguageLink server]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:54.91122+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:11.691776+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "uAjiAZCdDQC/qqUDA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[A custom snippet type]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
|
@@ -232,7 +232,119 @@
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:20.565513+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:20.565513+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "UXDVu4+dDQC/fqHFA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Building a LanguageLink client]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:33.223032+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:33.223032+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "6dWWvI+dDQC/gM7QA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Building a LanguageLink server]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:45.88618+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:48.608001+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "rYmTAZCdDQC/qIzPA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[What now?]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
@@ -265,6 +377,118 @@
|
||||
},
|
||||
"string" : "[[Executing code]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:07:50.665361+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:07:59.692968+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "3NNC/o+dDQC/oLtxA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Hooking up your LanguageLink server]]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:54.91122+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:11.691776+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "uAjiAZCdDQC/qqUDA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[A custom snippet type]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:03.097269+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:05.781133+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "j+IkapCdDQCBVgDCA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "[[Fin]]"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
|
@@ -325,14 +325,14 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:07:38.104346+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T16:35:43.289314+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "Ddc1ljyZDQCZq2mSDqn2mw=="
|
||||
},
|
||||
"code" : "; this is what we will be able to do\r(IO.defn hello-world []\r (IO.println \"Hello world!\"))"
|
||||
"code" : "; this is what we will be able to do\r(defn hello-world []\r (IO.println \"Hello world!\"))"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
|
@@ -325,7 +325,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:08:04.346367+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T16:35:43.289314+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -359,7 +359,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T16:54:20.656267+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T17:10:18.677811+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
|
113
lepiter/98eic2g8xrl1zoo0c1rpxqe78.bak
Normal file
113
lepiter/98eic2g8xrl1zoo0c1rpxqe78.bak
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T11:30:43.257961+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T20:46:56.443327+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "JUkMyTyZDQCZxrrZDqn2mw=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Getting code to execute is most likely the most tricky part of adding a language to GT. Most of the code in the Carp IDE deals with handling that part of the IDE experience. Additionally, {{gtPackage:LanguageLink requires a custom server setup, which needed to be written outside of GT."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:48:20.869905+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:02.268331+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "dwEUdoqdDQC+EJoFA3UANg=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Because both parts of this process make a cohesive whole, I split this chapter into two sub-chapters, [[Building a LanguageLink client]] and [[Building a LanguageLink server]]."
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:10:47.300048+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:10:47.300048+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Executing code"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "647f0bc9-3c99-0d00-99c5-5d710ea9f69b"
|
||||
}
|
||||
}
|
@@ -18,7 +18,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:10:53.313378+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T11:30:43.257961+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
@@ -29,7 +29,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:10:53.833743+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T20:47:09.979091+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -39,7 +39,44 @@
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "TODO"
|
||||
"string" : "Getting code to execute is most likely the most tricky part of adding a language to GT. Most of the code in the Carp IDE deals with handling that part of the IDE experience. Additionally, LanguageLink requires a custom server setup, which needed to be written outside of GT."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:48:20.869905+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:02.268331+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "dwEUdoqdDQC+EJoFA3UANg=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Because both parts of this process make a cohesive whole, I split this chapter into two sub-chapters, [[Building a LanguageLink client]] and [[Building a LanguageLink server]]."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -103,7 +103,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T18:04:44.753707+02:00"
|
||||
"dateAndTimeString" : "2022-04-18T21:16:33.659248+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -113,7 +113,7 @@
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Apart from that, I fear, I cannot help you much if things don’t go as planned. But maybe some of the things we will discuss in the next section, [[Building a parser from scratch]], will help you get from something that generates a raw parse tree to something that generates a real usable AST for your language. Take a peek!"
|
||||
"string" : "Apart from that, I fear, I cannot help you much if things don’t go as planned. But maybe some of the things we will discuss in the next section, [[Building a parser from scratch]], will help you get from something that generates a raw parse tree to something that generates a real usable AST for your language (look at Step II if you want to skip ahead). Take a peek!"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -66,7 +66,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T18:03:21.19204+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T20:48:50.30896+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
|
@@ -510,7 +510,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-18T21:22:40.888776+02:00"
|
||||
"dateAndTimeString" : "2022-04-18T21:22:56.54305+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -520,7 +520,7 @@
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "If you need another, simple example for a complete parser generating an"
|
||||
"string" : "If you need another, simple example for a complete parser generating an AST, you might want to check out the {{gtClass:JSONParser}}."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
|
@@ -214,7 +214,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-18T21:12:52.520639+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T20:49:10.152867+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
|
@@ -140,7 +140,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:57:41.124314+02:00"
|
||||
"dateAndTimeString" : "2022-04-17T17:58:06.623815+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -150,7 +150,7 @@
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "You might also want to take a look at the esecti{{gtPage:How to parse sources in different languages|db=2j9m7db2i4oz116bexd7wbdxo}}"
|
||||
"string" : "You might also want to take a look at the section {{gtPage:How to parse sources in different languages|db=2j9m7db2i4oz116bexd7wbdxo}} in the Glamorous Toolkit book to get an overview. Maybe the language you want to add is already there!"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -140,7 +140,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T17:58:06.623815+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T20:48:23.867543+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
|
@@ -140,7 +140,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-10T16:44:28.640047+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T20:50:28.716326+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -177,7 +177,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-10T16:47:01.610149+02:00"
|
||||
"dateAndTimeString" : "2022-06-10T16:47:24.613405+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -187,7 +187,7 @@
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In Carp, I also went down the extra mile of coloring parentheses according to their nesting level. The code for this is inside the rule for lists, maps and arrays, and it uses {{gtClass:CarpStylerUtilities}} to color the parentheses and register an event for when the cursor enters or leaves the region to highlight it. Should you want more complex highlighting and change it based on cursor position"
|
||||
"string" : "In Carp, I also went down the extra mile of coloring parentheses according to their nesting level. The code for this is inside the rule for lists, maps and arrays, and it uses {{gtClass:CarpStylerUtilities}} to color the parentheses and register an event for when the cursor enters or leaves the region to highlight it. Should you want more complex highlighting and change it based on cursor position and interactions, this might give you a taste of how to do it."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -140,7 +140,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-10T16:44:28.640047+02:00"
|
||||
"dateAndTimeString" : "2022-06-11T20:50:30.609796+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
|
@@ -103,14 +103,14 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T19:36:14.725535+02:00"
|
||||
"dateAndTimeString" : "2022-06-13T22:57:31.662829+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "yC3J0D6ZDQCd0ZgmDqn2mw=="
|
||||
},
|
||||
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: (CarpCall function: '+' asCarpSymbol arguments: { \r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol }));\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
|
||||
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: {}'+' asCarpSymbol arguments: { \r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol }));\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
@@ -248,7 +248,7 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T19:40:10.759445+02:00"
|
||||
"dateAndTimeString" : "2022-04-17T19:40:21.249005+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
@@ -258,7 +258,7 @@
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In the next chapter, we will use this code generator in our newly created coder"
|
||||
"string" : "In the next chapter named [[A coder of one’s own]], we will use this code generator in our newly created coder."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@@ -103,14 +103,14 @@
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-04-17T19:36:14.725535+02:00"
|
||||
"dateAndTimeString" : "2022-06-13T22:57:42.883096+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "yC3J0D6ZDQCd0ZgmDqn2mw=="
|
||||
},
|
||||
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: (CarpCall function: '+' asCarpSymbol arguments: { \r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol }));\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
|
||||
"code" : "'Example' asCarpModule\r\taddExpression: (CarpStaticFunction\r\t\t\t named: 'example' asCarpSymbol\r\t\t\t withArguments: { \r\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t 'y' asCarpSymbol }\r\t\t\t andBody: {'+' asCarpSymbol .\r\t\t\t\t\t\t\t 'x' asCarpSymbol.\r\t\t\t\t\t\t\t 'y' asCarpSymbol } asCarpCall);\r\taddExpression: (CarpDynamicVariable\r\t\t\t named: 'dyn-example' asCarpSymbol\r\t\t\t binding: 1 asCarpInteger);\r\ttoCarp"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
|
258
lepiter/9py149rplidcvk0jjdlnxeufv.bak
Normal file
258
lepiter/9py149rplidcvk0jjdlnxeufv.bak
Normal file
@@ -0,0 +1,258 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:27.48233+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:42.790324+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "n0WyA5CdDQC/sEIUA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Now that we have a LanguageLink server, we are all set, right? Well, not quite."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:49.137549+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:10:53.048149+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "YxldBZCdDQC/s15wA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Usually, a LanguageLink server is used within snippets as a driver for code execution. While you can use it yourself to execute some custom code and find some pleasure in that, we will first need an interface to type code *into* to make it truly worth our while."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:10:55.085183+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:11:56.629038+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "ChpOCZCdDQC/tYwmA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "But I understand that after all of the effort of building a LanguageLink implementation for your target you’re itching to try it out, so I’ll give you a little teaser of how it’s going to be used in the snippet:"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:11:58.378929+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:12:53.87069+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "BW4QDZCdDQC/tz6wA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "{{gtMethod:GtCarpCoderModel>>#bindAndExecute:|expanded}}"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:13:00.938416+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:13:26.816542+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "LBHBEJCdDQC/9sJRA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "This means that a simple snippet to test your LanguageLink implementation might look like this:"
|
||||
},
|
||||
{
|
||||
"__type" : "pharoSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:13:37.920717+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:18:19.754957+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "EjsQE5CdDQC/+NLCA8ExpA=="
|
||||
},
|
||||
"code" : "sourceString := '(IO.println \"Hello World!\")'.\t\"change this to your language\"\r\rapplication := CarpApplication uniqueInstance. \"change this to your application, might need to initialize the unique instance\"\rapplication isRunning ifFalse: [ application start ].\rcommandFactory := application newCommandFactory.\r\rcommandFactory\r\t<< sourceString;\r\tsendAndWait"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:20.062163+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:20.062163+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "What now?"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "9b9eb103-909d-0d00-bfaf-1b1203c131a4"
|
||||
}
|
||||
}
|
295
lepiter/9py149rplidcvk0jjdlnxeufv.lepiter
Normal file
295
lepiter/9py149rplidcvk0jjdlnxeufv.lepiter
Normal file
@@ -0,0 +1,295 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:27.48233+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:42.790324+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "n0WyA5CdDQC/sEIUA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Now that we have a LanguageLink server, we are all set, right? Well, not quite."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:49.137549+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:10:53.048149+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "YxldBZCdDQC/s15wA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Usually, a LanguageLink server is used within snippets as a driver for code execution. While you can use it yourself to execute some custom code and find some pleasure in that, we will first need an interface to type code *into* to make it truly worth our while."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:10:55.085183+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:11:56.629038+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "ChpOCZCdDQC/tYwmA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "But I understand that after all of the effort of building a LanguageLink implementation for your target you’re itching to try it out, so I’ll give you a little teaser of how it’s going to be used in the snippet:"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:11:58.378929+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:12:53.87069+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "BW4QDZCdDQC/tz6wA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "{{gtMethod:GtCarpCoderModel>>#bindAndExecute:|expanded}}"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:13:00.938416+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:13:26.816542+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "LBHBEJCdDQC/9sJRA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "This means that a simple snippet to test your LanguageLink implementation might look like this:"
|
||||
},
|
||||
{
|
||||
"__type" : "pharoSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:13:37.920717+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:18:32.957333+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "EjsQE5CdDQC/+NLCA8ExpA=="
|
||||
},
|
||||
"code" : "sourceString := '(IO.println \"Hello World!\")'.\t\"change this to your language\"\r\rapplication := CarpApplication uniqueInstance.\t\"change this to your application, might need to initialize the unique instance\"\rapplication isRunning ifFalse: [ application start ].\rcommandFactory := application newCommandFactory.\r\rcommandFactory\r\t<< sourceString;\r\tsendAndWait"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:18:42.650713+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:18:48.915283+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "pPclJZCdDQCADqoCA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "And that should be all you need to get going!"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:20.062163+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:20.062163+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "What now?"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "9b9eb103-909d-0d00-bfaf-1b1203c131a4"
|
||||
}
|
||||
}
|
187
lepiter/9py149svgo06hri6l3ym0kvvu.bak
Normal file
187
lepiter/9py149svgo06hri6l3ym0kvvu.bak
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:18:58.358497+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:19:44.830424+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "n4phA5CdDQC/rbQ7A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "After the doozy that is setting up LanguageLink, you might think that making a custom snippet type is going to be even more effort. I’ve got good news for you."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:19:51.016989+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T20:45:57.641893+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "Occ9KZCdDQCAEXGwA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Creating a snippet type is actually quite simple. Almost all of the code for Carp is in {{gtPackage:Carp}}. The most important class is likely {{gtClass:LeCarpSnippet}}, because like {{gtClass:CarpApplication}} for LanguageLink, this class is the central player around which the rest of the team organizes."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:25:29.637968+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:29:42.230718+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "pS1HPZCdDQCAOUdiA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Most of the code you will write will just be specialization over readily-available Lepiter classes. The only things that will be truly custom will most likely be your version of {{gtClass:LeExternalServerStrategy}} (in the case of Carp that is {{gtClass:LeCarpApplicationStrategy}}), which will bridge the gap between your LanguageLink application and the snippet itself, and your {{gtClass:GtSourceCoder}} ({{gtClass:GtCarpCoderModel}})."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:28:08.711515+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:28:15.191912+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "Dv7PRJCdDQCASGWFA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "But more about that in the next section!"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:14.768068+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:14.768068+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "A custom snippet type"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "6ad66003-909d-0d00-bfac-dd3803c131a4"
|
||||
}
|
||||
}
|
187
lepiter/9py149svgo06hri6l3ym0kvvu.lepiter
Normal file
187
lepiter/9py149svgo06hri6l3ym0kvvu.lepiter
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:18:58.358497+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:19:44.830424+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "n4phA5CdDQC/rbQ7A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "After the doozy that is setting up LanguageLink, you might think that making a custom snippet type is going to be even more effort. I’ve got good news for you."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:19:51.016989+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T20:46:02.5892+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "Occ9KZCdDQCAEXGwA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Creating a snippet type is actually quite simple. Almost all of the code for Carp is in {{gtPackage:Carp|tag=Lepiter}}. The most important class is likely {{gtClass:LeCarpSnippet}}, because like {{gtClass:CarpApplication}} for LanguageLink, this class is the central player around which the rest of the team organizes."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:25:29.637968+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:29:42.230718+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "pS1HPZCdDQCAOUdiA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Most of the code you will write will just be specialization over readily-available Lepiter classes. The only things that will be truly custom will most likely be your version of {{gtClass:LeExternalServerStrategy}} (in the case of Carp that is {{gtClass:LeCarpApplicationStrategy}}), which will bridge the gap between your LanguageLink application and the snippet itself, and your {{gtClass:GtSourceCoder}} ({{gtClass:GtCarpCoderModel}})."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:28:08.711515+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:28:15.191912+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "Dv7PRJCdDQCASGWFA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "But more about that in the next section!"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:14.768068+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:09:14.768068+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "A custom snippet type"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "6ad66003-909d-0d00-bfac-dd3803c131a4"
|
||||
}
|
||||
}
|
150
lepiter/9py149sz34c10e429aqq1v7qc.bak
Normal file
150
lepiter/9py149sz34c10e429aqq1v7qc.bak
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:59:53.327975+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:01:42.598848+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "bUpMu4+dDQC/fPzrA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Theoretically, you can use any technology that supports HTTP, JSON, and possibly MessagePack to construct a LanguageLink server, and you might be tempted to just do it in the language you are targetting, especially since it is quite likely that you are comfortable in it."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:01:44.277599+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-12T12:51:14.365509+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "Yzt86I+dDQC/lywBA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "I too was tempted to go down that route before realizing that that would mean understanding and implementing the LanguageLink protocol, a task I wasn’t particularly interested in. Instead, the Carp LanguageLink server uses the one provided by PythonBridge (which can be found [in the PythonBridge repository TODO:](https://github.com/feenkcom/PythonBridge/tree/master/PythonBridgeRuntime)). It includes all the infrastructure needed, and the only thing that likely needs to be changed is how `EvalCommand`s are handled: in the case of Carp, a simple subprocess handler that feeds the statements into a Carp REPL and reads the result. You can inspect the custom code I wrote [in the gt4carp repository TODO: good link](https://git.veitheller.de/carpentry/gt4carp)."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:06:15.752492+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:07:40.565555+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "tJmV+I+dDQC/nrmHA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "While I understand that this is a rather terse “figure it out yourself”, I don’t know the ins and outs of the LanguageLink protocol well enough to assist you any more—precisely because I took the effort of side-stepping the issue entirely. Hopefully you can too!"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:05.418793+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:05.418793+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Building a LanguageLink server"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "e4a14bbb-8f9d-0d00-bf7b-383c03c131a4"
|
||||
}
|
||||
}
|
150
lepiter/9py149sz34c10e429aqq1v7qc.lepiter
Normal file
150
lepiter/9py149sz34c10e429aqq1v7qc.lepiter
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:59:53.327975+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:01:42.598848+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "bUpMu4+dDQC/fPzrA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Theoretically, you can use any technology that supports HTTP, JSON, and possibly MessagePack to construct a LanguageLink server, and you might be tempted to just do it in the language you are targetting, especially since it is quite likely that you are comfortable in it."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:01:44.277599+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-12T12:51:15.652112+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "Yzt86I+dDQC/lywBA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "I too was tempted to go down that route before realizing that that would mean understanding and implementing the LanguageLink protocol, a task I wasn’t particularly interested in. Instead, the Carp LanguageLink server uses the one provided by PythonBridge (which can be found [in the PythonBridge repository](https://github.com/feenkcom/PythonBridge/tree/master/PythonBridgeRuntime)). It includes all the infrastructure needed, and the only thing that likely needs to be changed is how `EvalCommand`s are handled: in the case of Carp, a simple subprocess handler that feeds the statements into a Carp REPL and reads the result. You can inspect the custom code I wrote [in the gt4carp repository TODO: good link](https://git.veitheller.de/carpentry/gt4carp)."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:06:15.752492+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:07:40.565555+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "tJmV+I+dDQC/nrmHA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "While I understand that this is a rather terse “figure it out yourself”, I don’t know the ins and outs of the LanguageLink protocol well enough to assist you any more—precisely because I took the effort of side-stepping the issue entirely. Hopefully you can too!"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:05.418793+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:05.418793+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Building a LanguageLink server"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "e4a14bbb-8f9d-0d00-bf7b-383c03c131a4"
|
||||
}
|
||||
}
|
261
lepiter/9py149upn2jn86ntqk68tvld1.bak
Normal file
261
lepiter/9py149upn2jn86ntqk68tvld1.bak
Normal file
@@ -0,0 +1,261 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:28:18.00762+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:30:10.327276+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "xNZI/4+dDQC/o+CfA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Finally, finally we get to have a snippet type that actually knows how to execute code!"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:30:14.076728+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:31:02.274958+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "t3BjTpCdDQCAUTe6A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "To make that happen, we will need an application strategy. Building one should be fairly straightforward, since it mostly holds onto your LanguageLink application and builds new ones if needed."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:31:19.494771+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:32:06.868833+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "E6NbUZCdDQCAU8nsA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "More interesting will be your coder model, which is responsible for taking source code from an application, handing it over to LanguageLink, and displaying the result. As such, it is the main link between the IDE and the execution engine."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:32:07.688865+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:34:29.49505+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "ypstVZCdDQCAYOo/A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In the section [[What now?]] I already showcased the method that is most central to that process: `bindAndExecute:`. In my case, {{gtMethod:GtCarpCoderModel>>#bindAndExecute:|expanded}} is the final result. A quick refresher:"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:34:40.493148+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:36:37.301362+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "WALsXZCdDQCBUGyRA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "The method will take in a source string directly from coder and send it off to the evaluator handled by the LanguageLink application. Before that happens, though, it will most likely add some funky code around the snippet to capture the statement as a variable if possible, to allow for better interaction with GT."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:36:42.952545+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:37:23.855402+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "R7ljZZCdDQCBUlkLA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "It might be more useful for you to start with a trimmed-down version of this method that doesn’t do anything with the bindings and just hands over the source string as-is. To harness the full power of interacting with G"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:06.046507+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:06.046507+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Hooking up your LanguageLink server"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "e53a48ff-8f9d-0d00-bfa2-217603c131a4"
|
||||
}
|
||||
}
|
261
lepiter/9py149upn2jn86ntqk68tvld1.lepiter
Normal file
261
lepiter/9py149upn2jn86ntqk68tvld1.lepiter
Normal file
@@ -0,0 +1,261 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:28:18.00762+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:30:10.327276+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "xNZI/4+dDQC/o+CfA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Finally, finally we get to have a snippet type that actually knows how to execute code!"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:30:14.076728+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:31:02.274958+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "t3BjTpCdDQCAUTe6A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "To make that happen, we will need an application strategy. Building one should be fairly straightforward, since it mostly holds onto your LanguageLink application and builds new ones if needed."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:31:19.494771+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:32:06.868833+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "E6NbUZCdDQCAU8nsA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "More interesting will be your coder model, which is responsible for taking source code from an application, handing it over to LanguageLink, and displaying the result. As such, it is the main link between the IDE and the execution engine."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:32:07.688865+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:34:29.49505+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "ypstVZCdDQCAYOo/A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In the section [[What now?]] I already showcased the method that is most central to that process: `bindAndExecute:`. In my case, {{gtMethod:GtCarpCoderModel>>#bindAndExecute:|expanded}} is the final result. A quick refresher:"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:34:40.493148+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:36:37.301362+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "WALsXZCdDQCBUGyRA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "The method will take in a source string directly from coder and send it off to the evaluator handled by the LanguageLink application. Before that happens, though, it will most likely add some funky code around the snippet to capture the statement as a variable if possible, to allow for better interaction with GT."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:36:42.952545+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:37:38.760779+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "R7ljZZCdDQCBUlkLA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "It might be more useful for you to start with a trimmed-down version of this method that doesn’t do anything with the bindings and just hands over the source string as-is. To harness the full power of interacting with GT, however, we will need to send variables and values back and forth sooner or later."
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:06.046507+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:08:06.046507+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Hooking up your LanguageLink server"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "e53a48ff-8f9d-0d00-bfa2-217603c131a4"
|
||||
}
|
||||
}
|
224
lepiter/9py149uso8srjrtyq6opyrmzh.bak
Normal file
224
lepiter/9py149uso8srjrtyq6opyrmzh.bak
Normal file
@@ -0,0 +1,224 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:08.96254+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:10.799078+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "6bymapCdDQCBW13UA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "You made it!"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:12.929099+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:56.257815+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "IW3tapCdDQCBXcd8A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "If you read this booklet linearly from start to finish and followed along with your own implementation, you should now be able to execute code in custom Lepiter snippets! Exciting indeed!"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:59.504959+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:40:09.625312+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "4R2abZCdDQCBX8vQA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Now, of course, the fun doesn’t stop here. For full interactivity, we might need to (de)serialize values in an almost seamless manner, like JSLink does. To do that, we will have to make GT understand our language semantically rather than just syntactically."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:40:10.264658+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:41:08.513478+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "kHzzcZCdDQCBYawWA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "We could also start using GT’s powers to visualize things about our codebase or to generate code, or we might want to create a custom IDE. Some of these fun adventures you will have to embark on on your own, but if you want some inspiration, the [[Bonus Chapters]] might hold some interest to you."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:41:12.090085+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:41:24.342689+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "nEKhdZCdDQCBgxEjA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "I hope you enjoyed our little journey, congratulate you to your new po"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:07.35881+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:07.35881+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Fin"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "1d13a66a-909d-0d00-815a-f07803c131a4"
|
||||
}
|
||||
}
|
224
lepiter/9py149uso8srjrtyq6opyrmzh.lepiter
Normal file
224
lepiter/9py149uso8srjrtyq6opyrmzh.lepiter
Normal file
@@ -0,0 +1,224 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:08.96254+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:10.799078+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "6bymapCdDQCBW13UA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "You made it!"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:12.929099+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:56.257815+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "IW3tapCdDQCBXcd8A8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "If you read this booklet linearly from start to finish and followed along with your own implementation, you should now be able to execute code in custom Lepiter snippets! Exciting indeed!"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:59.504959+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:40:09.625312+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "4R2abZCdDQCBX8vQA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Now, of course, the fun doesn’t stop here. For full interactivity, we might need to (de)serialize values in an almost seamless manner, like JSLink does. To do that, we will have to make GT understand our language semantically rather than just syntactically."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:40:10.264658+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:41:08.513478+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "kHzzcZCdDQCBYawWA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "We could also start using GT’s powers to visualize things about our codebase or to generate code, or we might want to create a custom IDE. Some of these fun adventures you will have to embark on on your own, but if you want some inspiration, the [[Bonus Chapters]] might hold some interest to you."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:41:12.090085+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:41:41.069403+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "nEKhdZCdDQCBgxEjA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "I hope you enjoyed our little journey and congratulate you to your new powers! See you around."
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:07.35881+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T18:38:07.35881+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Fin"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "1d13a66a-909d-0d00-815a-f07803c131a4"
|
||||
}
|
||||
}
|
224
lepiter/9py149ytik0od40b9dfzhll4q.bak
Normal file
224
lepiter/9py149ytik0od40b9dfzhll4q.bak
Normal file
@@ -0,0 +1,224 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:47.434396+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:50:11.430885+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "YVM4u4+dDQC/eTezA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Building a LanguageLink client is easy, but not necessarily simple, since it involves writing a lot of mostly glue code."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:50:15.711236+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:52:49.226165+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "suJsv4+dDQC/h6EvA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "As an entry-point, you will have to write a {{gtClass:LanguageLinkApplication}}. The (very spartan) one for Carp is {{gtClass:CarpApplication}}. Writing the application will give you a lay of the land, since it’s the central piece of infrastructure that holds on to all the rest."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:52:50.001285+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:53:48.39118+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "/4qmyI+dDQC/i6IPA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In the Carp application, I tried to use stock classes from LanguageLink wherever possible. Only when that didn’t work did I add classes. I also took inspiration from {{gtClass:JSLinkApplication}}, since it was there and seemed to provide rich functionality."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:53:50.150304+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:57:15.031561+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "hy01zI+dDQC/j6rJA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In total, all the classes that needed filling in were {{gtClass:CarpPostMortemDebugger}} (used in: {{gtMethod:CarpApplication>>debuggerClientFor:}}), {{gtClass:CarpExecutionHandler}} (used in {{gtMethod:CarpApplication>>#initializeHandlers}}), and all the classes in {{gtMethod:LanguageLinkSettings class>>carpDefaultSettings|expanded}} prefixed with `Carp`:"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:57:33.45648+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:59:17.862655+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "sPXB2I+dDQC/k6TTA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Implementing and understanding all of these classes might seem like a daunting task, and in many ways it is. But implementing most of these classes is simple and doesn’t at first require a thorough understanding of the system, at least that was the case for me. This means that you can just browse the existing implementors of any specific piece of infrastructure and “compare notes”. This approach got me f"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:04.110462+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:04.110462+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Building a LanguageLink client"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "3aab37bb-8f9d-0d00-bf78-07ff03c131a4"
|
||||
}
|
||||
}
|
224
lepiter/9py149ytik0od40b9dfzhll4q.lepiter
Normal file
224
lepiter/9py149ytik0od40b9dfzhll4q.lepiter
Normal file
@@ -0,0 +1,224 @@
|
||||
{
|
||||
"__schema" : "4.1",
|
||||
"__type" : "page",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:47.434396+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:50:11.430885+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "YVM4u4+dDQC/eTezA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Building a LanguageLink client is easy, but not necessarily simple, since it involves writing a lot of mostly glue code."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:50:15.711236+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:52:49.226165+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "suJsv4+dDQC/h6EvA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "As an entry-point, you will have to write a {{gtClass:LanguageLinkApplication}}. The (very spartan) one for Carp is {{gtClass:CarpApplication}}. Writing the application will give you a lay of the land, since it’s the central piece of infrastructure that holds on to all the rest."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:52:50.001285+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:53:48.39118+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "/4qmyI+dDQC/i6IPA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In the Carp application, I tried to use stock classes from LanguageLink wherever possible. Only when that didn’t work did I add classes. I also took inspiration from {{gtClass:JSLinkApplication}}, since it was there and seemed to provide rich functionality."
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:53:50.150304+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:57:15.031561+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "hy01zI+dDQC/j6rJA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "In total, all the classes that needed filling in were {{gtClass:CarpPostMortemDebugger}} (used in: {{gtMethod:CarpApplication>>debuggerClientFor:}}), {{gtClass:CarpExecutionHandler}} (used in {{gtMethod:CarpApplication>>#initializeHandlers}}), and all the classes in {{gtMethod:LanguageLinkSettings class>>carpDefaultSettings|expanded}} prefixed with `Carp`:"
|
||||
},
|
||||
{
|
||||
"__type" : "textSnippet",
|
||||
"children" : {
|
||||
"__type" : "snippets",
|
||||
"items" : [ ]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:57:33.45648+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:59:36.36081+02:00"
|
||||
}
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uid",
|
||||
"uidString" : "sPXB2I+dDQC/k6TTA8ExpA=="
|
||||
},
|
||||
"paragraphStyle" : {
|
||||
"__type" : "textStyle"
|
||||
},
|
||||
"string" : "Implementing and understanding all of these classes might seem like a daunting task, and in many ways it is. But implementing most of these classes is simple and doesn’t at first require a thorough understanding of the system, at least that was the case for me. This means that you can just browse the existing implementors of any specific piece of infrastructure and “compare notes”. This approach got me far enough to build a first version (with a little bit of added debugging), and it might get you there too!"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"createTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:04.110462+02:00"
|
||||
}
|
||||
},
|
||||
"editEmail" : {
|
||||
"__type" : "email",
|
||||
"emailString" : "<unknown>"
|
||||
},
|
||||
"editTime" : {
|
||||
"__type" : "time",
|
||||
"time" : {
|
||||
"__type" : "dateAndTime",
|
||||
"dateAndTimeString" : "2022-06-11T17:49:04.110462+02:00"
|
||||
}
|
||||
},
|
||||
"pageType" : {
|
||||
"__type" : "namedPage",
|
||||
"title" : "Building a LanguageLink client"
|
||||
},
|
||||
"uid" : {
|
||||
"__type" : "uuid",
|
||||
"uuid" : "3aab37bb-8f9d-0d00-bf78-07ff03c131a4"
|
||||
}
|
||||
}
|
@@ -2,5 +2,5 @@
|
||||
"uuid" : "de53e067-3c99-0d00-9999-34310ea9f69b",
|
||||
"tableOfContents" : "98eic2d1mangtosf26n3aq420",
|
||||
"schema" : "4.1",
|
||||
"databaseName" : "Adding a Language to the Glamorous Toolkit"
|
||||
"databaseName" : "Adding a Language to Glamorous Toolkit"
|
||||
}
|
@@ -6,11 +6,13 @@ Class {
|
||||
|
||||
{ #category : #baseline }
|
||||
BaselineOfCarp >> baseline: spec [
|
||||
|
||||
<baseline>
|
||||
spec for: #common do: [
|
||||
spec
|
||||
baseline: 'GToolkit4SmaCC'
|
||||
with: [ spec repository: 'github://feenkcom/gt4smacc:main/src' ].
|
||||
spec package: 'Carp' with: [ spec requires: #( 'GToolkit4SmaCC' ) ] ]
|
||||
spec
|
||||
for: #common
|
||||
do: [ spec
|
||||
baseline: 'GToolkit4SmaCC'
|
||||
with: [ spec repository: 'github://feenkcom/gt4smacc:main/src' ].
|
||||
spec package: 'Carp' with: [ spec requires: #('GToolkit4SmaCC') ].
|
||||
spec package: 'Carp-AST' with: [ spec requires: #('GToolkit4SmaCC') ].
|
||||
spec package: 'Carp-Parser' with: [ spec requires: #('GToolkit4SmaCC') ] ]
|
||||
]
|
||||
|
@@ -13,6 +13,16 @@ CarpCharacterNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitCharacter: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCharacterNode >> intoModel [
|
||||
^ CarpCharacter character: self value source asCharacter
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCharacterNode >> toPharo [
|
||||
^ value source asCharacter
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpCharacterNode >> tokenVariables [
|
||||
|
||||
|
@@ -16,6 +16,16 @@ CarpExpressionNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitExpression: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpressionNode >> isDefinition [
|
||||
^ false
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpressionNode >> isDefinitionPredicate [
|
||||
^ false
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpressionNode >> isQuoted [
|
||||
^ parent ifNil: [ false ] ifNotNil: [ parent isQuoted ]
|
||||
@@ -25,3 +35,8 @@ CarpExpressionNode >> isQuoted [
|
||||
CarpExpressionNode >> listDepth [
|
||||
^ parent ifNil: [ 0 ] ifNotNil: [ parent listDepth + 1 ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpressionNode >> toPharo [
|
||||
^ self subclassResponsibility
|
||||
]
|
||||
|
@@ -13,6 +13,16 @@ CarpNumberNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitNumber: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpNumberNode >> intoModel [
|
||||
^ CarpDouble number: self value source asNumber
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpNumberNode >> toPharo [
|
||||
^ value source asInteger
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpNumberNode >> tokenVariables [
|
||||
|
||||
|
@@ -34,6 +34,11 @@ CarpPairNode >> nodeVariables [
|
||||
^ #( #key #value )
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPairNode >> toPharo [
|
||||
^ Association key: key toPharo value: value toPharo
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpPairNode >> value [
|
||||
|
||||
|
@@ -29,6 +29,11 @@ CarpQuoteNode >> nodeVariables [
|
||||
^ #( #value )
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpQuoteNode >> toPharo [
|
||||
^ {#quote . value toPharo }
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpQuoteNode >> value [
|
||||
|
||||
|
@@ -38,3 +38,14 @@ CarpStartNode >> initialize [
|
||||
super initialize.
|
||||
expressions := OrderedCollection new: 2.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpStartNode >> intoModel [
|
||||
self assert: self expressions size = 1.
|
||||
^ self expressions first intoModel
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpStartNode >> toPharo [
|
||||
^ expressions collect: #toPharo
|
||||
]
|
||||
|
@@ -13,6 +13,16 @@ CarpStringNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitString: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpStringNode >> intoModel [
|
||||
^ CarpStringExpression contents: self value source
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpStringNode >> toPharo [
|
||||
^ value source
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpStringNode >> tokenVariables [
|
||||
|
||||
|
@@ -13,6 +13,25 @@ CarpVariableNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitVariable: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpVariableNode >> intoModel [
|
||||
^ CarpSymbol named: self value source
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpVariableNode >> isDefinitionPredicate [
|
||||
^ {'defdynamic'.
|
||||
'defndynamic'.
|
||||
'defmacro'.
|
||||
'defn'.
|
||||
'def'} includes: self value source
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpVariableNode >> toPharo [
|
||||
^ value source asSymbol
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpVariableNode >> tokenVariables [
|
||||
|
||||
|
@@ -41,6 +41,11 @@ CarpArrayNode >> initialize [
|
||||
expressions := OrderedCollection new: 2.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpArrayNode >> intoModel [
|
||||
^ CarpArray contents: (expressions collect: #intoModel)
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpArrayNode >> leftBracket [
|
||||
|
||||
@@ -65,6 +70,11 @@ CarpArrayNode >> rightBracket: aSmaCCToken [
|
||||
rightBracket := aSmaCCToken
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpArrayNode >> toPharo [
|
||||
^ expressions collect: #toPharo
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpArrayNode >> tokenVariables [
|
||||
|
||||
|
@@ -26,12 +26,22 @@ CarpDerefNode >> derefGlyph: aSmaCCToken [
|
||||
derefGlyph := aSmaCCToken
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpDerefNode >> intoModel [
|
||||
^ CarpCall function: 'deref' arguments: {value intoModel}
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpDerefNode >> nodeVariables [
|
||||
|
||||
^ #( #value )
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpDerefNode >> toPharo [
|
||||
^ {#deref . value toPharo}
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpDerefNode >> tokenVariables [
|
||||
|
||||
|
@@ -21,6 +21,14 @@ CarpListNode >> compositeNodeVariables [
|
||||
^ #( #expressions )
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpListNode >> definitionVariable [
|
||||
^ (self expressions size > 1
|
||||
and: [ self expressions first isDefinitionPredicate ])
|
||||
ifTrue: [ self expressions second ]
|
||||
ifFalse: [ nil ]
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpListNode >> expressions [
|
||||
|
||||
@@ -41,6 +49,27 @@ CarpListNode >> initialize [
|
||||
expressions := OrderedCollection new: 2.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpListNode >> intoModel [
|
||||
^ self isDefinition
|
||||
ifTrue: [ | binding |
|
||||
binding := (CarpBinding perform: self expressions first value source asSymbol)
|
||||
name: self definitionVariable intoModel.
|
||||
self expressions size = 3
|
||||
ifTrue: [ binding binding: self expressions third intoModel ].
|
||||
self expressions size = 4
|
||||
ifTrue: [ binding
|
||||
arguments: self expressions third intoModel;
|
||||
body: self expressions fourth intoModel ].
|
||||
binding ]
|
||||
ifFalse: [ CarpList contents: (expressions collect: #intoModel) ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpListNode >> isDefinition [
|
||||
^ self definitionVariable isNotNil
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpListNode >> leftParen [
|
||||
|
||||
@@ -65,6 +94,11 @@ CarpListNode >> rightParen: aSmaCCToken [
|
||||
rightParen := aSmaCCToken
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpListNode >> toPharo [
|
||||
^ expressions collect: #toPharo
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpListNode >> tokenVariables [
|
||||
|
||||
|
@@ -27,6 +27,15 @@ CarpMapNode >> initialize [
|
||||
pairs := OrderedCollection new: 2.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpMapNode >> intoModel [
|
||||
^ CarpMap
|
||||
contents: (pairs
|
||||
flatCollect: [ :p |
|
||||
{p key intoModel.
|
||||
p value intoModel} ])
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpMapNode >> leftBrace [
|
||||
|
||||
@@ -65,6 +74,11 @@ CarpMapNode >> rightBrace: aSmaCCToken [
|
||||
rightBrace := aSmaCCToken
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpMapNode >> toPharo [
|
||||
^ (pairs collect: #toPharo) asDictionary
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpMapNode >> tokenVariables [
|
||||
|
||||
|
@@ -14,6 +14,14 @@ CarpModuleOrTypeNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitModuleOrType: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpModuleOrTypeNode >> intoModel [
|
||||
^ CarpSymbol
|
||||
named: ('.'
|
||||
join: {module source.
|
||||
value source})
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpModuleOrTypeNode >> module [
|
||||
|
||||
@@ -32,6 +40,11 @@ CarpModuleOrTypeNode >> nodeVariables [
|
||||
^ #( #value )
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpModuleOrTypeNode >> toPharo [
|
||||
^ value source asSymbol
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpModuleOrTypeNode >> tokenVariables [
|
||||
|
||||
|
@@ -6,7 +6,7 @@ Class {
|
||||
|
||||
{ #category : #'generated-accessing' }
|
||||
CarpParser class >> cacheId [
|
||||
^'2022-04-17T17:01:25.369965+02:00'
|
||||
^'2022-06-13T14:48:36.40126+02:00'
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
@@ -16,6 +16,26 @@ CarpParser class >> definitionComment [
|
||||
%root Expression;
|
||||
%prefix Carp;
|
||||
%suffix Node;
|
||||
|
||||
%hierarchy Expression (
|
||||
Array
|
||||
Deref
|
||||
List
|
||||
Map
|
||||
ModuleOrType
|
||||
Pattern
|
||||
RefCall
|
||||
Ref
|
||||
Unquote
|
||||
Character
|
||||
Number
|
||||
Pair
|
||||
Quote
|
||||
Start
|
||||
String
|
||||
Variable
|
||||
);
|
||||
|
||||
<escape>
|
||||
: \\ (. | u[0-9A-F]{4,4} | o[0-7]{3,3} | newline | return | space | tab | space | backspace | formfeed) # other character types
|
||||
;
|
||||
@@ -155,44 +175,44 @@ String
|
||||
{ #category : #generated }
|
||||
CarpParser class >> reduceTable [
|
||||
^#(
|
||||
#(24 0 #reduceActionForExpressions1: 1289217 false)
|
||||
#(23 1 #reduceActionForStart1: 1258497 false)
|
||||
#(32 0 #reduceActionForExpressions1: 1803265 false)
|
||||
#(43 1 #reduceActionForString1: 2446337 false)
|
||||
#(40 1 #reduceActionForVariable1: 2233345 false)
|
||||
#(41 1 #reduceActionForModuleOrType2: 2273282 false)
|
||||
#(36 1 #reduceActionForNumber1: 2013185 false)
|
||||
#(35 1 #reduceActionForCharacter1: 1971201 false)
|
||||
#(24 2 #reduceActionForExpressions2: 1289218 false)
|
||||
#(25 1 #liftFirstValue: 1347588 false)
|
||||
#(25 1 #liftFirstValue: 1347589 false)
|
||||
#(25 1 #liftFirstValue: 1347587 false)
|
||||
#(25 1 #liftFirstValue: 1347586 false)
|
||||
#(25 1 #liftFirstValue: 1347585 false)
|
||||
#(30 1 #liftFirstValue: 1652745 false)
|
||||
#(30 1 #liftFirstValue: 1652744 false)
|
||||
#(30 1 #liftFirstValue: 1652743 false)
|
||||
#(30 1 #liftFirstValue: 1652742 false)
|
||||
#(30 1 #liftFirstValue: 1652739 false)
|
||||
#(30 1 #liftFirstValue: 1652741 false)
|
||||
#(30 1 #liftFirstValue: 1652740 false)
|
||||
#(39 1 #liftFirstValue: 2195458 false)
|
||||
#(39 1 #liftFirstValue: 2195457 false)
|
||||
#(30 1 #liftFirstValue: 1652738 false)
|
||||
#(30 1 #liftFirstValue: 1652737 false)
|
||||
#(34 2 #reduceActionForPattern1: 1906689 false)
|
||||
#(27 2 #reduceActionForUnquote1: 1466369 false)
|
||||
#(27 2 #reduceActionForUnquote1: 1466370 false)
|
||||
#(28 2 #reduceActionForRef1: 1548289 false)
|
||||
#(29 2 #reduceActionForDeref1: 1598465 false)
|
||||
#(26 2 #reduceActionForRefCall1: 1412097 false)
|
||||
#(38 2 #reduceActionForQuote1: 2150401 false)
|
||||
#(31 3 #reduceActionForMap1: 1744897 false)
|
||||
#(32 2 #reduceActionForExpressions2: 1803266 false)
|
||||
#(42 3 #reduceActionForList1: 2364417 false)
|
||||
#(41 3 #reduceActionForModuleOrType1: 2273281 false)
|
||||
#(37 3 #reduceActionForArray1: 2059265 false)
|
||||
#(33 2 #reduceActionForMapPair1: 1846273 false)
|
||||
#(24 0 #reduceActionForExpressions1: 1449985 false)
|
||||
#(23 1 #reduceActionForStart1: 1419265 false)
|
||||
#(32 0 #reduceActionForExpressions1: 1964033 false)
|
||||
#(43 1 #reduceActionForString1: 2607105 false)
|
||||
#(40 1 #reduceActionForVariable1: 2394113 false)
|
||||
#(41 1 #reduceActionForModuleOrType2: 2434050 false)
|
||||
#(36 1 #reduceActionForNumber1: 2173953 false)
|
||||
#(35 1 #reduceActionForCharacter1: 2131969 false)
|
||||
#(24 2 #reduceActionForExpressions2: 1449986 false)
|
||||
#(25 1 #liftFirstValue: 1508356 false)
|
||||
#(25 1 #liftFirstValue: 1508357 false)
|
||||
#(25 1 #liftFirstValue: 1508355 false)
|
||||
#(25 1 #liftFirstValue: 1508354 false)
|
||||
#(25 1 #liftFirstValue: 1508353 false)
|
||||
#(30 1 #liftFirstValue: 1813513 false)
|
||||
#(30 1 #liftFirstValue: 1813512 false)
|
||||
#(30 1 #liftFirstValue: 1813511 false)
|
||||
#(30 1 #liftFirstValue: 1813510 false)
|
||||
#(30 1 #liftFirstValue: 1813507 false)
|
||||
#(30 1 #liftFirstValue: 1813509 false)
|
||||
#(30 1 #liftFirstValue: 1813508 false)
|
||||
#(39 1 #liftFirstValue: 2356226 false)
|
||||
#(39 1 #liftFirstValue: 2356225 false)
|
||||
#(30 1 #liftFirstValue: 1813506 false)
|
||||
#(30 1 #liftFirstValue: 1813505 false)
|
||||
#(34 2 #reduceActionForPattern1: 2067457 false)
|
||||
#(27 2 #reduceActionForUnquote1: 1627137 false)
|
||||
#(27 2 #reduceActionForUnquote1: 1627138 false)
|
||||
#(28 2 #reduceActionForRef1: 1709057 false)
|
||||
#(29 2 #reduceActionForDeref1: 1759233 false)
|
||||
#(26 2 #reduceActionForRefCall1: 1572865 false)
|
||||
#(38 2 #reduceActionForQuote1: 2311169 false)
|
||||
#(31 3 #reduceActionForMap1: 1905665 false)
|
||||
#(32 2 #reduceActionForExpressions2: 1964034 false)
|
||||
#(42 3 #reduceActionForList1: 2525185 false)
|
||||
#(41 3 #reduceActionForModuleOrType1: 2434049 false)
|
||||
#(37 3 #reduceActionForArray1: 2220033 false)
|
||||
#(33 2 #reduceActionForMapPair1: 2007041 false)
|
||||
).
|
||||
]
|
||||
|
||||
|
@@ -26,6 +26,11 @@ CarpPatternNode >> patternGlyph: aSmaCCToken [
|
||||
patternGlyph := aSmaCCToken
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPatternNode >> toPharo [
|
||||
^ value source
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpPatternNode >> tokenVariables [
|
||||
|
||||
|
@@ -14,6 +14,11 @@ CarpRefCallNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitRefCall: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpRefCallNode >> intoModel [
|
||||
^ CarpCall function: '~' arguments: {value intoModel}
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpRefCallNode >> nodeVariables [
|
||||
|
||||
@@ -32,6 +37,11 @@ CarpRefCallNode >> refGlyph: aSmaCCToken [
|
||||
refGlyph := aSmaCCToken
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpRefCallNode >> toPharo [
|
||||
^ {#'ref-call' . value toPharo}
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpRefCallNode >> tokenVariables [
|
||||
|
||||
|
@@ -14,6 +14,11 @@ CarpRefNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitRef: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpRefNode >> intoModel [
|
||||
^ CarpCall function: 'ref' arguments: {value intoModel}
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpRefNode >> nodeVariables [
|
||||
|
||||
@@ -32,6 +37,11 @@ CarpRefNode >> refGlyph: aSmaCCToken [
|
||||
refGlyph := aSmaCCToken
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpRefNode >> toPharo [
|
||||
^ {#ref . value toPharo}
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpRefNode >> tokenVariables [
|
||||
|
||||
|
@@ -30,80 +30,72 @@ CarpScanner >> scan1 [
|
||||
|
||||
{ #category : #generated }
|
||||
CarpScanner >> scan2 [
|
||||
|
||||
self recordMatch: #( 13 ).
|
||||
self recordMatch: #(13).
|
||||
self step.
|
||||
currentCharacter isDigit ifTrue: [ ^ self scan3 ].
|
||||
(currentCharacter isLowercase or: [
|
||||
currentCharacter isUppercase or: [
|
||||
('!$' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $* and: $+) or: [
|
||||
('-/:' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $< and: $?) or: [
|
||||
currentCharacter == $_ ] ] ] ] ] ]) ifTrue: [
|
||||
[
|
||||
self recordMatch: #( 13 ).
|
||||
self step.
|
||||
currentCharacter isLowercase or: [
|
||||
currentCharacter isUppercase or: [
|
||||
currentCharacter isDigit or: [
|
||||
('!$' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $* and: $+) or: [
|
||||
('-/:' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $< and: $?) or: [
|
||||
currentCharacter == $_ ] ] ] ] ] ] ] ] whileTrue ].
|
||||
(currentCharacter isLowercase
|
||||
or: [ currentCharacter isUppercase
|
||||
or: [ ('!$' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $* and: $+)
|
||||
or: [ currentCharacter == $-
|
||||
or: [ (currentCharacter between: $/ and: $:)
|
||||
or: [ (currentCharacter between: $< and: $?) or: [ currentCharacter == $_ ] ] ] ] ] ] ])
|
||||
ifTrue: [ [ self recordMatch: #(13).
|
||||
self step.
|
||||
currentCharacter isLowercase
|
||||
or: [ currentCharacter isUppercase
|
||||
or: [ currentCharacter isDigit
|
||||
or: [ ('!$' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $* and: $+)
|
||||
or: [ ('-/:' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $< and: $?) or: [ currentCharacter == $_ ] ] ] ] ] ] ] ]
|
||||
whileTrue ].
|
||||
^ self reportLastMatch
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpScanner >> scan3 [
|
||||
|
||||
[
|
||||
self recordMatch: #( 13 18 ).
|
||||
[ self recordMatch: #(13 18).
|
||||
self step.
|
||||
currentCharacter == $. ifTrue: [ ^ self scan4 ].
|
||||
currentCharacter isDigit ] whileTrue.
|
||||
('bfl' includes: currentCharacter) ifTrue: [
|
||||
self recordMatch: #( 13 18 ).
|
||||
self step.
|
||||
(currentCharacter isLowercase or: [
|
||||
currentCharacter isUppercase or: [
|
||||
currentCharacter isDigit or: [
|
||||
('!$' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $* and: $+) or: [
|
||||
('-/:' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $< and: $?) or: [
|
||||
currentCharacter == $_ ] ] ] ] ] ] ]) ifTrue: [
|
||||
[
|
||||
self recordMatch: #( 13 ).
|
||||
('bfl' includes: currentCharacter)
|
||||
ifTrue: [ self recordMatch: #(13 18).
|
||||
self step.
|
||||
currentCharacter isLowercase or: [
|
||||
currentCharacter isUppercase or: [
|
||||
currentCharacter isDigit or: [
|
||||
('!$' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $* and: $+) or: [
|
||||
('-/:' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $< and: $?) or: [
|
||||
currentCharacter == $_ ] ] ] ] ] ] ] ] whileTrue ].
|
||||
^ self reportLastMatch ].
|
||||
(currentCharacter isUppercase or: [
|
||||
currentCharacter isLowercase or: [
|
||||
('!$' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $* and: $+) or: [
|
||||
('-/:' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $< and: $?) or: [
|
||||
currentCharacter == $_ ] ] ] ] ] ]) ifTrue: [
|
||||
[
|
||||
self recordMatch: #( 13 ).
|
||||
self step.
|
||||
currentCharacter isLowercase or: [
|
||||
currentCharacter isUppercase or: [
|
||||
currentCharacter isDigit or: [
|
||||
('!$' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $* and: $+) or: [
|
||||
('-/:' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $< and: $?) or: [
|
||||
currentCharacter == $_ ] ] ] ] ] ] ] ] whileTrue ].
|
||||
(currentCharacter isLowercase
|
||||
or: [ currentCharacter isUppercase
|
||||
or: [ currentCharacter isDigit
|
||||
or: [ ('!$' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $* and: $+)
|
||||
or: [ ('-/:' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $< and: $?) or: [ currentCharacter == $_ ] ] ] ] ] ] ])
|
||||
ifTrue: [ [ self recordMatch: #(13).
|
||||
self step.
|
||||
currentCharacter isLowercase
|
||||
or: [ currentCharacter isUppercase
|
||||
or: [ currentCharacter isDigit
|
||||
or: [ ('!$' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $* and: $+)
|
||||
or: [ ('-/:' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $< and: $?) or: [ currentCharacter == $_ ] ] ] ] ] ] ] ]
|
||||
whileTrue ].
|
||||
^ self reportLastMatch ].
|
||||
(currentCharacter isUppercase
|
||||
or: [ currentCharacter isLowercase
|
||||
or: [ ('!$' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $* and: $+)
|
||||
or: [ (currentCharacter between: $- and: $:)
|
||||
or: [ (currentCharacter between: $< and: $?) or: [ currentCharacter == $_ ] ] ] ] ] ])
|
||||
ifTrue: [ [ self recordMatch: #(13).
|
||||
self step.
|
||||
currentCharacter isLowercase
|
||||
or: [ currentCharacter isUppercase
|
||||
or: [ currentCharacter isDigit
|
||||
or: [ ('!$' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $* and: $+)
|
||||
or: [ ('-/:' includes: currentCharacter)
|
||||
or: [ (currentCharacter between: $< and: $?) or: [ currentCharacter == $_ ] ] ] ] ] ] ] ]
|
||||
whileTrue ].
|
||||
^ self reportLastMatch
|
||||
]
|
||||
|
||||
@@ -152,12 +144,9 @@ CarpScanner >> scan7 [
|
||||
|
||||
{ #category : #generated }
|
||||
CarpScanner >> scanForToken [
|
||||
|
||||
self step.
|
||||
currentCharacter == $" ifTrue: [ ^ self scan1 ].
|
||||
currentCharacter == $# ifTrue: [ ^ self recordAndReportMatch: #( 1 ) ].
|
||||
currentCharacter == $% ifTrue: [ ^ self scanForTokenX7 ].
|
||||
currentCharacter == $& ifTrue: [ ^ self recordAndReportMatch: #( 4 ) ].
|
||||
currentCharacter == $# ifTrue: [ ^ self recordAndReportMatch: #(1) ].
|
||||
^ self scanForTokenX9
|
||||
]
|
||||
|
||||
@@ -330,47 +319,36 @@ CarpScanner >> scanForTokenX7 [
|
||||
|
||||
{ #category : #generated }
|
||||
CarpScanner >> scanForTokenX8 [
|
||||
|
||||
currentCharacter == $} ifTrue: [ ^ self recordAndReportMatch: #( 7 ) ].
|
||||
currentCharacter == $~ ifTrue: [ ^ self recordAndReportMatch: #( 8 ) ].
|
||||
currentCharacter == $] ifTrue: [ ^ self recordAndReportMatch: #(17) ].
|
||||
currentCharacter == ${ ifTrue: [ ^ self recordAndReportMatch: #(6) ].
|
||||
currentCharacter == $} ifTrue: [ ^ self recordAndReportMatch: #(7) ].
|
||||
currentCharacter == $~ ifTrue: [ ^ self recordAndReportMatch: #(8) ].
|
||||
currentCharacter isDigit ifTrue: [ ^ self scan5 ].
|
||||
('''`' includes: currentCharacter) ifTrue: [
|
||||
^ self recordAndReportMatch: #( 12 ) ].
|
||||
(currentCharacter isSeparator or: [
|
||||
currentCharacter == Character pageUp ]) ifTrue: [
|
||||
^ self scanForTokenX6 ].
|
||||
('''`' includes: currentCharacter)
|
||||
ifTrue: [ ^ self recordAndReportMatch: #(12) ].
|
||||
(currentCharacter isSeparator or: [ currentCharacter == Character pageUp ])
|
||||
ifTrue: [ ^ self scanForTokenX6 ].
|
||||
currentCharacter isUppercase ifTrue: [ ^ self scanForTokenX3 ].
|
||||
(currentCharacter isLowercase or: [
|
||||
('!$' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $* and: $+) or: [
|
||||
('/:' includes: currentCharacter) or: [
|
||||
(currentCharacter between: $< and: $?) or: [
|
||||
currentCharacter == $_ ] ] ] ] ]) ifTrue: [
|
||||
self scanForTokenX4 ].
|
||||
(currentCharacter isLowercase
|
||||
or: [ (currentCharacter between: $! and: $?) or: [ currentCharacter == $_ ] ])
|
||||
ifTrue: [ self scanForTokenX4 ].
|
||||
^ self reportLastMatch
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpScanner >> scanForTokenX9 [
|
||||
|
||||
currentCharacter == $( ifTrue: [
|
||||
^ self recordAndReportMatch: #( 10 ) ].
|
||||
currentCharacter == $) ifTrue: [
|
||||
^ self recordAndReportMatch: #( 11 ) ].
|
||||
currentCharacter == $, ifTrue: [
|
||||
^ self recordAndReportMatch: #( 19 ) ].
|
||||
currentCharacter == $% ifTrue: [ ^ self scanForTokenX7 ].
|
||||
currentCharacter == $& ifTrue: [ ^ self recordAndReportMatch: #(4) ].
|
||||
currentCharacter == $( ifTrue: [ ^ self recordAndReportMatch: #(10) ].
|
||||
currentCharacter == $) ifTrue: [ ^ self recordAndReportMatch: #(11) ].
|
||||
currentCharacter == $, ifTrue: [ ^ self recordAndReportMatch: #(19) ].
|
||||
currentCharacter == $- ifTrue: [ ^ self scan2 ].
|
||||
currentCharacter == $. ifTrue: [
|
||||
^ self recordAndReportMatch: #( 15 ) ].
|
||||
currentCharacter == $. ifTrue: [ ^ self recordAndReportMatch: #(15) ].
|
||||
currentCharacter == $0 ifTrue: [ ^ self scanForTokenX2 ].
|
||||
currentCharacter == $; ifTrue: [ ^ self scanForTokenX5 ].
|
||||
currentCharacter == $@ ifTrue: [ ^ self recordAndReportMatch: #( 5 ) ].
|
||||
currentCharacter == $[ ifTrue: [
|
||||
^ self recordAndReportMatch: #( 16 ) ].
|
||||
currentCharacter == $@ ifTrue: [ ^ self recordAndReportMatch: #(5) ].
|
||||
currentCharacter == $[ ifTrue: [ ^ self recordAndReportMatch: #(16) ].
|
||||
currentCharacter == $\ ifTrue: [ ^ self scanForTokenX1 ].
|
||||
currentCharacter == $] ifTrue: [
|
||||
^ self recordAndReportMatch: #( 17 ) ].
|
||||
currentCharacter == ${ ifTrue: [ ^ self recordAndReportMatch: #( 6 ) ].
|
||||
^ self scanForTokenX8
|
||||
]
|
||||
|
||||
|
@@ -14,6 +14,11 @@ CarpUnquoteNode >> acceptVisitor: anExpressionVisitor [
|
||||
^ anExpressionVisitor visitUnquote: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpUnquoteNode >> intoModel [
|
||||
^ CarpCall function: 'unquote' arguments: {value intoModel}
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpUnquoteNode >> isQuoted [
|
||||
^ false
|
||||
@@ -25,6 +30,11 @@ CarpUnquoteNode >> nodeVariables [
|
||||
^ #( #value )
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpUnquoteNode >> toPharo [
|
||||
^ {#unquote . value toPharo}
|
||||
]
|
||||
|
||||
{ #category : #generated }
|
||||
CarpUnquoteNode >> tokenVariables [
|
||||
|
||||
|
@@ -13,6 +13,11 @@ CarpApplication class >> start [
|
||||
^ self startWith: LanguageLinkSettings carpDefaultSettings.
|
||||
]
|
||||
|
||||
{ #category : #'class initialization' }
|
||||
CarpApplication class >> startUp: resuming [
|
||||
resuming ifTrue: [ self stop ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpApplication >> baseApplication [
|
||||
^ CarpApplication
|
||||
|
15
src/Carp/CarpArray.class.st
Normal file
15
src/Carp/CarpArray.class.st
Normal file
@@ -0,0 +1,15 @@
|
||||
Class {
|
||||
#name : #CarpArray,
|
||||
#superclass : #CarpSequence,
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpArray >> close [
|
||||
^ ']'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpArray >> open [
|
||||
^ '['
|
||||
]
|
@@ -7,6 +7,31 @@ Class {
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpBinding class >> def [
|
||||
^ CarpStaticVariable new
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpBinding class >> defdynamic [
|
||||
^ CarpDynamicVariable new
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpBinding class >> defmacro [
|
||||
^ CarpMacro new
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpBinding class >> defn [
|
||||
^ CarpStaticFunction new
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpBinding class >> defndynamic [
|
||||
^ CarpDynamicFunction new
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpBinding >> bindingName [
|
||||
^ self subclassResponsibility
|
||||
|
28
src/Carp/CarpCharacter.class.st
Normal file
28
src/Carp/CarpCharacter.class.st
Normal file
@@ -0,0 +1,28 @@
|
||||
Class {
|
||||
#name : #CarpCharacter,
|
||||
#superclass : #CarpLiteral,
|
||||
#instVars : [
|
||||
'character'
|
||||
],
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpCharacter class >> character: aCharacter [
|
||||
^ self new character: aCharacter
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCharacter >> character [
|
||||
^ character
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCharacter >> character: aCharacter [
|
||||
character := aCharacter
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCharacter >> toCarp [
|
||||
^ '\', self character
|
||||
]
|
51
src/Carp/CarpCliOutput.class.st
Normal file
51
src/Carp/CarpCliOutput.class.st
Normal file
@@ -0,0 +1,51 @@
|
||||
Class {
|
||||
#name : #CarpCliOutput,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'text'
|
||||
],
|
||||
#category : #'Carp-Core'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCliOutput class >> text: aString [
|
||||
^ self new text: aString
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCliOutput >> gtExitCodeFor: aView [
|
||||
<gtView>
|
||||
^ aView forward
|
||||
title: 'Exit Code';
|
||||
priority: 2;
|
||||
object: [ self text lines last asInteger ];
|
||||
view: #gtLiveFor:
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCliOutput >> gtOutputFor: aView [
|
||||
<gtView>
|
||||
^ aView textEditor
|
||||
title: 'Output';
|
||||
priority: 1;
|
||||
text: [ Character lf join: (self text lines allButLast: 2) ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCliOutput >> gtRawOutputFor: aView [
|
||||
<gtView>
|
||||
^ aView textEditor
|
||||
title: 'Raw Output';
|
||||
priority: 3;
|
||||
text: [ self text ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCliOutput >> text [
|
||||
^ text
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCliOutput >> text: aString [
|
||||
text := aString
|
||||
]
|
10
src/Carp/CarpCommand.class.st
Normal file
10
src/Carp/CarpCommand.class.st
Normal file
@@ -0,0 +1,10 @@
|
||||
Class {
|
||||
#name : #CarpCommand,
|
||||
#superclass : #LanguageLinkCommand,
|
||||
#category : #'Carp-LanguageLink'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCommand >> codeForRemote [
|
||||
^ (Character space join: self instructions) copyReplaceAll: Character cr asString with: Character lf asString
|
||||
]
|
@@ -3,3 +3,13 @@ Class {
|
||||
#superclass : #LanguageLinkCommandFactory,
|
||||
#category : #'Carp-Execution'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCommandFactory >> command [
|
||||
^ command
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpCommandFactory >> instructionsWithNotifyAtEnd [
|
||||
^ instructions
|
||||
]
|
||||
|
@@ -4,19 +4,19 @@ Class {
|
||||
#category : #'Carp-Serialization'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpDeserializer class >> deserialize: anObject [
|
||||
^ self new
|
||||
deserialize: anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpDeserializer >> buildProxyFor: rawObject [
|
||||
| proxy |
|
||||
proxy := CarpProxyObject
|
||||
carpType: (rawObject at: #carptype)
|
||||
var: (rawObject at: #carpvar) asJSGI
|
||||
var: (rawObject at: #carpvar)
|
||||
application: self application.
|
||||
self executionHandler registerObject: proxy.
|
||||
^ proxy
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpDeserializer >> deserialize: anObject [
|
||||
^ self new
|
||||
deserialize: anObject
|
||||
]
|
||||
|
@@ -3,3 +3,8 @@ Class {
|
||||
#superclass : #CarpNumber,
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpDouble >> suffix [
|
||||
^ ''
|
||||
]
|
||||
|
68
src/Carp/CarpExecutionResult.class.st
Normal file
68
src/Carp/CarpExecutionResult.class.st
Normal file
@@ -0,0 +1,68 @@
|
||||
Class {
|
||||
#name : #CarpExecutionResult,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'value',
|
||||
'warnings',
|
||||
'view'
|
||||
],
|
||||
#category : #'Carp-Execution'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpExecutionResult class >> from: aCarpResult [
|
||||
^ self new
|
||||
value: (aCarpResult at: #value);
|
||||
warnings: (aCarpResult at: #warnings)
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> gtValueFor: aView [
|
||||
<gtView>
|
||||
| v |
|
||||
v := aView forward
|
||||
title: 'Value';
|
||||
priority: 1;
|
||||
object: value.
|
||||
view ifNotNil: [ v view: view ].
|
||||
^ v
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> gtWarningsFor: aView [
|
||||
<gtView>
|
||||
^ aView list
|
||||
title: 'Warnings';
|
||||
priority: 2;
|
||||
items: [ warnings ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> parse [
|
||||
value := CarpParser parse: value
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> transformValue: aBlock [
|
||||
value := aBlock value: value
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> value [
|
||||
^ value
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> value: aValue [
|
||||
value := aValue
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> view: aView [
|
||||
view := aView
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExecutionResult >> warnings: aCollection [
|
||||
warnings := aCollection
|
||||
]
|
@@ -12,6 +12,17 @@ CarpExpression >> asElement [
|
||||
^ (GtCarpCoderModel code: self toCarp) asElement
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpression >> asElementWithModule: aModule [
|
||||
| applicationStrategy |
|
||||
applicationStrategy := LeCarpApplicationStrategy new.
|
||||
^ (GtExpandableSourceCoderElement new
|
||||
coderViewModel: ((GtCarpIDECoderModel code: self toCarp)
|
||||
module: aModule;
|
||||
carpLinkApplicationStrategy: applicationStrategy;
|
||||
expression: self) asCoderViewModel) collapse
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpression >> documentation [
|
||||
^ documentation ifNil: ['']
|
||||
@@ -22,6 +33,24 @@ CarpExpression >> documentation: aString [
|
||||
documentation := aString
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpression >> gtCoderFor: aView [
|
||||
<gtView>
|
||||
^ aView explicit
|
||||
title: 'Code';
|
||||
priority: 1;
|
||||
stencil: [ self asElement ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpExpression >> gtTextFor: aView [
|
||||
<gtView>
|
||||
^ aView textEditor
|
||||
title: 'String';
|
||||
priority: 2;
|
||||
text: [ self toCarp ]
|
||||
]
|
||||
|
||||
{ #category : #converting }
|
||||
CarpExpression >> toCarp [
|
||||
^ self subclassResponsibility
|
||||
|
15
src/Carp/CarpList.class.st
Normal file
15
src/Carp/CarpList.class.st
Normal file
@@ -0,0 +1,15 @@
|
||||
Class {
|
||||
#name : #CarpList,
|
||||
#superclass : #CarpSequence,
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpList >> close [
|
||||
^ ')'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpList >> open [
|
||||
^ '('
|
||||
]
|
15
src/Carp/CarpMap.class.st
Normal file
15
src/Carp/CarpMap.class.st
Normal file
@@ -0,0 +1,15 @@
|
||||
Class {
|
||||
#name : #CarpMap,
|
||||
#superclass : #CarpSequence,
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpMap >> close [
|
||||
^ '}'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpMap >> open [
|
||||
^ '{'
|
||||
]
|
@@ -67,8 +67,7 @@ CarpModule >> carpCoderCommentsFor: aView [
|
||||
{ #category : #coders }
|
||||
CarpModule >> carpCoderStreamingMethodsFor: aView context: aPhlowContext [
|
||||
<gtModuleView>
|
||||
| aMethodsCoder aMethodsCoderViewModel aNewMethodCoderHolder |
|
||||
|
||||
| aMethodsCoder aMethodsCoderViewModel aNewMethodCoderHolder coderElement |
|
||||
aNewMethodCoderHolder := ValueHolder new.
|
||||
|
||||
^ aView explicit
|
||||
@@ -76,46 +75,36 @@ CarpModule >> carpCoderStreamingMethodsFor: aView context: aPhlowContext [
|
||||
title: 'Methods';
|
||||
disableAsync;
|
||||
actionDropdownButtonDo: [ :aDrodownAction |
|
||||
aDrodownAction dropdown
|
||||
aDrodownAction dropdown
|
||||
icon: BrGlamorousVectorIcons add;
|
||||
tooltip: 'Add new expression';
|
||||
content: [ :aButton |
|
||||
tooltip: 'Add new function';
|
||||
content: [ :aButton |
|
||||
| aNewMethodCoder aNewMethodCoderViewModel aHandler |
|
||||
|
||||
aNewMethodCoderHolder contents
|
||||
ifNotNil: [ :aContents |
|
||||
aNewMethodCoderViewModel := aContents ]
|
||||
ifNil: [
|
||||
|
||||
aNewMethodCoder := GtCarpCoderModel new.
|
||||
ifNotNil: [ :aContents | aNewMethodCoderViewModel := aContents ]
|
||||
ifNil: [ aNewMethodCoder := GtCarpNewFunctionCoderModel new
|
||||
module: self;
|
||||
carpLinkApplicationStrategy: LeCarpApplicationStrategy new;
|
||||
onSave: [ aButton fireEvent: BrDropdownHideWish new.
|
||||
coderElement initializeForModule ].
|
||||
|
||||
aNewMethodCoderViewModel := aNewMethodCoder asCoderViewModel.
|
||||
aNewMethodCoderViewModel
|
||||
withoutHeader;
|
||||
expanded: true;
|
||||
focused: true;
|
||||
moveCursorAtEnd.
|
||||
|
||||
aNewMethodCoderHolder contents: aNewMethodCoderViewModel.
|
||||
aNewMethodCoderViewModel := aNewMethodCoder asCoderViewModel.
|
||||
aNewMethodCoderViewModel
|
||||
withoutHeader;
|
||||
expanded: true;
|
||||
focused: true;
|
||||
moveCursorAtEnd.
|
||||
|
||||
aHandler := GtPharoNewMethodCodeSavedHandler new
|
||||
methodsCoderViewModel: aMethodsCoderViewModel;
|
||||
element: aButton;
|
||||
methodCoderHolder: aNewMethodCoderHolder.
|
||||
|
||||
aNewMethodCoderViewModel weak
|
||||
when: GtMethodCoderSaved
|
||||
send: #onAnnouncement:
|
||||
to: aHandler ].
|
||||
aNewMethodCoderHolder contents: aNewMethodCoderViewModel ].
|
||||
|
||||
(GtExpandedOnlyCoderElement new coderViewModel: aNewMethodCoderViewModel)
|
||||
hExact: 300;
|
||||
vFitContent;
|
||||
background: Color white;
|
||||
padding: (BlInsets all: 5);
|
||||
addAptitude: BrGlamorousFocusableShadowAptitude new ];
|
||||
name: #'button--add-new-expression'];
|
||||
stencil: [ CarpStreamingMethodsCoderElement forModule: self ]
|
||||
(GtExpandedOnlyCoderElement new coderViewModel: aNewMethodCoderViewModel)
|
||||
hExact: 300;
|
||||
vFitContent;
|
||||
background: Color white;
|
||||
padding: (BlInsets all: 5);
|
||||
addAptitude: BrGlamorousFocusableShadowAptitude new ];
|
||||
name: #'button--add-new-expression' ];
|
||||
stencil: [ coderElement := CarpStreamingMethodsCoderElement forModule: self ]
|
||||
]
|
||||
|
||||
{ #category : #coders }
|
||||
@@ -194,6 +183,11 @@ CarpModule >> name: aString [
|
||||
name := aString
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpModule >> removeExpression: anExpression [
|
||||
expressions remove: anExpression
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpModule >> removeUse: aString [
|
||||
uses remove: aString
|
||||
|
@@ -19,6 +19,15 @@ CarpModuleCoder >> asCoderViewModel [
|
||||
^ CarpModuleCoderViewModel new coder: self
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpModuleCoder >> coderName [
|
||||
"Return a short textual name of the coder.
|
||||
For example, class coder would return a class name, package coder returns a package name."
|
||||
<return: #String>
|
||||
|
||||
^ self module name
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpModuleCoder >> module [
|
||||
^ module
|
||||
|
@@ -12,6 +12,17 @@ Class {
|
||||
#category : #'Carp-Coder'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpModuleCoderElement >> build [
|
||||
| application commandFactory |
|
||||
application := CarpApplication start.
|
||||
commandFactory := application newCommandFactory.
|
||||
|
||||
^ commandFactory
|
||||
<< self module toCarp;
|
||||
sendAndWait
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpModuleCoderElement >> buildContentPane [
|
||||
|
||||
@@ -91,6 +102,13 @@ CarpModuleCoderElement >> buildModuleLabel [
|
||||
action: [ :aButton |
|
||||
aButton phlow spawnObject: self module toCarp ]).
|
||||
|
||||
aContainer addChild: (BrButton new
|
||||
aptitude: BrGlamorousButtonWithIconAptitude;
|
||||
icon: BrGlamorousVectorIcons refresh;
|
||||
beSmallSize;
|
||||
label: 'Build';
|
||||
action: [ self build ]).
|
||||
|
||||
^ aContainer
|
||||
]
|
||||
|
||||
@@ -133,7 +151,8 @@ CarpModuleCoderElement >> coderViewModel: aCarpCoderViewModel [
|
||||
|
||||
container ifNotNil: #removeFromParent.
|
||||
container := self buildContentPane.
|
||||
self addChildFirst: container
|
||||
self addChildFirst: container.
|
||||
self build
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
|
@@ -49,5 +49,5 @@ CarpNamedFunction >> toCarp [
|
||||
aStream << '(' << self bindingName << ' ' << self name toCarp
|
||||
<< ' ['.
|
||||
arguments do: [ :anArgument | aStream << anArgument toCarp << ' ' ].
|
||||
aStream << '] ' << self body toCarp << ')' ]
|
||||
aStream ensureNoSpace << '] ' << self body toCarp << ')' ]
|
||||
]
|
||||
|
10
src/Carp/CarpPattern.class.st
Normal file
10
src/Carp/CarpPattern.class.st
Normal file
@@ -0,0 +1,10 @@
|
||||
Class {
|
||||
#name : #CarpPattern,
|
||||
#superclass : #CarpStringExpression,
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPattern >> toCarp [
|
||||
^ '#', super toCarp
|
||||
]
|
@@ -7,6 +7,11 @@ Class {
|
||||
#category : #'Carp-Processes'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPlatform class >> uiManagerClass [
|
||||
^ LanguageLinkPharoUiManager
|
||||
]
|
||||
|
||||
{ #category : #hooks }
|
||||
CarpPlatform class >> weakRegistryClass [
|
||||
^ LanguageLinkPharoWeakRegistry
|
||||
|
@@ -19,11 +19,20 @@ CarpPostMortemDebugger >> exception: anException [
|
||||
exception := anException
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPostMortemDebugger >> findTrace: inputLines [
|
||||
| lines |
|
||||
lines := inputLines asOrderedCollection.
|
||||
[ lines isNotEmpty and: [ (lines first = 'Traceback:') not ] ]
|
||||
whileTrue: [ lines removeFirst ].
|
||||
^ lines
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPostMortemDebugger >> initialize [
|
||||
|
||||
super initialize.
|
||||
frameRegex := '\s+at.+\(([^:]+)\:(\d+)\:(\d+)\)' asRegexIgnoringCase.
|
||||
frameRegex := '(.*)\s+at\s+([^:]+)\:(\d+)\:(\d+)\.' asRegexIgnoringCase.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@@ -37,16 +46,18 @@ CarpPostMortemDebugger >> sourceStyler [
|
||||
CarpPostMortemDebugger >> stackFrameFromLine: aString ordinal: ordinal [
|
||||
"Answer a frame if the supplied string contains a valid file and line number, or nil"
|
||||
<return: #GtPythonPostMortemStackFrame or: nil>
|
||||
| file line column |
|
||||
| file line column source |
|
||||
|
||||
^ (frameRegex search: aString) ifTrue:
|
||||
[ file := frameRegex subexpression: 2.
|
||||
line := frameRegex subexpression: 3.
|
||||
column := frameRegex subexpression: 4.
|
||||
[ source := frameRegex subexpression: 2.
|
||||
file := frameRegex subexpression: 3.
|
||||
line := frameRegex subexpression: 4.
|
||||
column := frameRegex subexpression: 5.
|
||||
CarpPostMortemStackFrame new
|
||||
ordinal: ordinal;
|
||||
displayString: aString;
|
||||
exception: exception;
|
||||
source: source;
|
||||
file: file asFileReference;
|
||||
line: line asNumber;
|
||||
column: column asNumber ]
|
||||
@@ -59,17 +70,28 @@ CarpPostMortemDebugger >> stackFrameFromLine: aString ordinal: ordinal [
|
||||
CarpPostMortemDebugger >> stackFrames [
|
||||
"Answer a ordered collection of stack frames.
|
||||
This is called many times by the debugger, so cache"
|
||||
|
||||
| ordinal |
|
||||
|
||||
^ stackFrames ifNil:
|
||||
[ ordinal := 1.
|
||||
stackFrames := OrderedCollection new.
|
||||
exception trace lines do: [ :line |
|
||||
(self stackFrameFromLine: line ordinal: ordinal) ifNotNil: [ :frame |
|
||||
stackFrames add: frame.
|
||||
ordinal := ordinal + 1 ] ].
|
||||
stackFrames ].
|
||||
|
||||
^ stackFrames
|
||||
ifNil: [ ordinal := 1.
|
||||
stackFrames := OrderedCollection new.
|
||||
(self findTrace: exception trace lines)
|
||||
do: [ :line |
|
||||
(self stackFrameFromLine: line ordinal: ordinal)
|
||||
ifNotNil: [ :frame |
|
||||
stackFrames add: frame.
|
||||
ordinal := ordinal + 1 ] ].
|
||||
(exception trace lines last beginsWith: '[RUNTIME ERROR]')
|
||||
ifTrue: [ stackFrames
|
||||
add: (CarpPostMortemStackFrame new
|
||||
ordinal: 1;
|
||||
displayString: exception trace lines last;
|
||||
exception: exception;
|
||||
source: exception trace lines last;
|
||||
file: 'REPL' asFileReference;
|
||||
line: 0;
|
||||
column: 0) ].
|
||||
stackFrames ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
|
@@ -1,5 +1,31 @@
|
||||
Class {
|
||||
#name : #CarpPostMortemStackFrame,
|
||||
#superclass : #GtJavaScriptPostMortemStackFrame,
|
||||
#instVars : [
|
||||
'source'
|
||||
],
|
||||
#category : #'Carp-Debugger'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPostMortemStackFrame >> source: aString [
|
||||
source := aString
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPostMortemStackFrame >> sourceText [
|
||||
| mySource text indexes lineNumber |
|
||||
file exists
|
||||
ifTrue: [ mySource := file contents.
|
||||
lineNumber := line ]
|
||||
ifFalse: [ ^ source asRopedText
|
||||
attribute: (BlTextHighlightAttribute paint: BrGlamorousColors errorBackgroundColor)
|
||||
beNotOverwritableByStyler ].
|
||||
text := mySource asRopedText.
|
||||
indexes := mySource gtIndexOfLineNumber: lineNumber.
|
||||
indexes
|
||||
ifNotNil: [ (text from: indexes key + column - 1 to: indexes value)
|
||||
attribute: (BlTextHighlightAttribute paint: BrGlamorousColors errorBackgroundColor)
|
||||
beNotOverwritableByStyler ].
|
||||
^ text
|
||||
]
|
||||
|
@@ -11,26 +11,27 @@ Class {
|
||||
#category : #'Carp-Processes'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpProcess class >> program [
|
||||
^ 'carp'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpProcess class >> resolveCarpPath [
|
||||
| proc |
|
||||
|
||||
proc := GtSubprocessWithInMemoryOutput new
|
||||
command: 'which';
|
||||
arguments: { 'carp' }.
|
||||
arguments: { self program}.
|
||||
CarpPlatform subProcessEnvironmentDictionary keysAndValuesDo: [ :key :value |
|
||||
proc environmentAt: key put: value ].
|
||||
proc runAndWait.
|
||||
(#(0 1) includes: proc exitCode) ifFalse:
|
||||
[ self error: 'Unable to request carp location' ].
|
||||
[ self error: 'Unable to request', self program, ' location' ].
|
||||
^ proc stdout trim asFileReference
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpProcess class >> resolveNodejsPath [
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpProcess class >> serverPath [
|
||||
^ CarpPath
|
||||
@@ -67,16 +68,17 @@ CarpProcess >> isRunning [
|
||||
ifNotNil: [ process isRunning ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpProcess >> newProcess| newProcess [ |
|
||||
{ #category : #'start-stop' }
|
||||
CarpProcess >> newProcess [
|
||||
| newProcess |
|
||||
newProcess := GtSubprocessWithInMemoryOutput new
|
||||
command: self serverPath fullName;
|
||||
arguments: self processArguments;
|
||||
workingDirectory: self workingDirectory resolve fullName;
|
||||
terminateOnShutdown;
|
||||
yourself.
|
||||
environmentVariables associationsDo: [ :assoc |
|
||||
newProcess environmentAt: assoc key put: assoc value ].
|
||||
command: self serverPath fullName;
|
||||
arguments: self processArguments;
|
||||
workingDirectory: self workingDirectory resolve fullName;
|
||||
terminateOnShutdown;
|
||||
yourself.
|
||||
environmentVariables
|
||||
associationsDo: [ :assoc | newProcess environmentAt: assoc key put: assoc value ].
|
||||
^ newProcess
|
||||
]
|
||||
|
||||
@@ -88,12 +90,17 @@ CarpProcess >> processArguments [
|
||||
self settings serverDebugMode ifTrue:
|
||||
[ args add: '--inspect' ].
|
||||
args
|
||||
add: (self workingDirectory / 'src/languagelink.carp') resolve fullName;
|
||||
add: (self workingDirectory / self programFile) resolve fullName;
|
||||
add: self settings serverSocketAddress port asString;
|
||||
add: self settings clientSocketAddress port asString.
|
||||
^ args
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpProcess >> programFile [
|
||||
^ 'src/languagelink.carp'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpProcess >> serverPath [
|
||||
| fileReference |
|
||||
|
46
src/Carp/CarpPythonProcess.class.st
Normal file
46
src/Carp/CarpPythonProcess.class.st
Normal file
@@ -0,0 +1,46 @@
|
||||
Class {
|
||||
#name : #CarpPythonProcess,
|
||||
#superclass : #CarpProcess,
|
||||
#category : #'Carp-Processes'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPythonProcess class >> program [
|
||||
^ 'python'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPythonProcess class >> resolveCarpPath [
|
||||
"TODO: make more robust"
|
||||
^ '/usr/bin/python' asFileReference
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPythonProcess >> processArguments [
|
||||
| args |
|
||||
|
||||
args := OrderedCollection new.
|
||||
self settings serverDebugMode ifTrue:
|
||||
[ args addAll: {
|
||||
'-m'.
|
||||
'debugpy'.
|
||||
'--listen'.
|
||||
self settings debugSocketAddress printAddress.
|
||||
'--wait-for-client'. } ].
|
||||
args
|
||||
add: (self workingDirectory / self programFile) resolve fullName;
|
||||
add: '--port';
|
||||
add: self settings serverSocketAddress port asString;
|
||||
add: '--pharo';
|
||||
add: self settings clientSocketAddress port asString;
|
||||
add: '--method';
|
||||
add: 'http'.
|
||||
"self debugMode ifTrue: [ args add: '--log' ]."
|
||||
args add: '--log'.
|
||||
^ args
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpPythonProcess >> programFile [
|
||||
^ 'src/languagelink.py'
|
||||
]
|
43
src/Carp/CarpSequence.class.st
Normal file
43
src/Carp/CarpSequence.class.st
Normal file
@@ -0,0 +1,43 @@
|
||||
Class {
|
||||
#name : #CarpSequence,
|
||||
#superclass : #CarpLiteral,
|
||||
#instVars : [
|
||||
'elements',
|
||||
'contents'
|
||||
],
|
||||
#category : #'Carp-IDE'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpSequence class >> contents: aCollection [
|
||||
^ self new contents: aCollection
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpSequence >> close [
|
||||
^ self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpSequence >> contents: aCollection [
|
||||
contents := aCollection
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpSequence >> do: aBlock [
|
||||
contents do: aBlock
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpSequence >> open [
|
||||
^ self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpSequence >> toCarp [
|
||||
|
||||
^ String streamContents: [ :aStream |
|
||||
aStream << self open.
|
||||
contents do: [ :anArgument | aStream << anArgument toCarp << ' ' ].
|
||||
aStream ensureNoSpace << self close]
|
||||
]
|
@@ -26,7 +26,7 @@ CarpStreamingMethodsCoderElement >> initialize [
|
||||
itemType: [ :anItemTypeFactory :anItemObject |
|
||||
anItemObject ];
|
||||
itemStencil: [ :anItem |
|
||||
anItem asElement id: GtSourceCoderId ];
|
||||
(anItem asElementWithModule: module) id: GtSourceCoderId ];
|
||||
itemsProvider:
|
||||
(BrListStreamItemsProvider new stream: AsyncEmptyStream new).
|
||||
|
||||
|
@@ -12,6 +12,11 @@ CarpSymbol class >> named: aString [
|
||||
^ self new name: aString
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpSymbol >> name [
|
||||
^ name
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpSymbol >> name: aString [
|
||||
name := aString
|
||||
|
199
src/Carp/CarpTypeSignature.class.st
Normal file
199
src/Carp/CarpTypeSignature.class.st
Normal file
@@ -0,0 +1,199 @@
|
||||
Class {
|
||||
#name : #CarpTypeSignature,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'signature',
|
||||
'model',
|
||||
'tooltipsContainer'
|
||||
],
|
||||
#category : #'Carp-Coder'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
CarpTypeSignature class >> on: aValue using: aModel [
|
||||
^ self new
|
||||
fromAST: aValue;
|
||||
model: aModel
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpTypeSignature >> elementsList [
|
||||
| tokens verticalContainer docsRegex |
|
||||
tokens := signature value source findTokens: ' () []'.
|
||||
docsRegex := 'Documentation\: (.*)' asRegexIgnoringCase.
|
||||
|
||||
verticalContainer := BrVerticalPane new
|
||||
fitContent;
|
||||
padding: (BlInsets all: 10).
|
||||
|
||||
tokens
|
||||
do: [ :each |
|
||||
| res |
|
||||
res := model bindAndExecuteRaw: '(info ' , each , ')'.
|
||||
(docsRegex search: (res at: #value))
|
||||
ifTrue: [ | docs |
|
||||
docs := docsRegex subexpression: 2.
|
||||
verticalContainer
|
||||
addChild: (BrLabel new
|
||||
aptitude: BrGlamorousLabelAptitude new
|
||||
+ (GtExplainerExplanationAptitude new explanationModel: each)
|
||||
+ (BrStyleCommonAptitude new
|
||||
hovered: [ :aStyle |
|
||||
aStyle background: BrGlamorousColors textHighlightColor.
|
||||
aStyle
|
||||
do: [ tooltipsContainer
|
||||
text: docs;
|
||||
visibility: BlVisibility visible ]
|
||||
after: [ tooltipsContainer
|
||||
text: '' asRopedText;
|
||||
visibility: BlVisibility gone ] ]);
|
||||
geometry: (BlRoundedRectangleGeometry cornerRadius: 4);
|
||||
text: each;
|
||||
padding: (BlInsets all: 5)) ] ].
|
||||
|
||||
(tokens includes: '<StaticLifetime>')
|
||||
ifTrue: [ verticalContainer
|
||||
addChild: (BrLabel new
|
||||
aptitude: BrGlamorousLabelAptitude new
|
||||
+ (GtExplainerExplanationAptitude new explanationModel: '<StaticLifetime>')
|
||||
+ (BrStyleCommonAptitude new
|
||||
hovered: [ :aStyle |
|
||||
aStyle background: BrGlamorousColors textHighlightColor.
|
||||
aStyle
|
||||
do: [ tooltipsContainer
|
||||
text: 'is the default static lifetime of values (this lifetime includes the entire program run).';
|
||||
visibility: BlVisibility visible ]
|
||||
after: [ tooltipsContainer
|
||||
text: '' asRopedText;
|
||||
visibility: BlVisibility gone ] ]);
|
||||
geometry: (BlRoundedRectangleGeometry cornerRadius: 4);
|
||||
text: '<StaticLifetime>';
|
||||
padding: (BlInsets all: 5)) ].
|
||||
|
||||
(tokens includes: 'Fn')
|
||||
ifTrue: [ verticalContainer
|
||||
addChild: (BrLabel new
|
||||
aptitude: BrGlamorousLabelAptitude new
|
||||
+ (GtExplainerExplanationAptitude new explanationModel: 'Fn')
|
||||
+ (BrStyleCommonAptitude new
|
||||
hovered: [ :aStyle |
|
||||
aStyle background: BrGlamorousColors textHighlightColor.
|
||||
aStyle
|
||||
do: [ tooltipsContainer
|
||||
text: 'is the function type and is read: ' asRopedText, '(Fn [<arguments>] <return type> <lifetime>).' asRopedText glamorousCodeFont;
|
||||
visibility: BlVisibility visible ]
|
||||
after: [ tooltipsContainer
|
||||
text: '' asRopedText;
|
||||
visibility: BlVisibility gone ] ]);
|
||||
geometry: (BlRoundedRectangleGeometry cornerRadius: 4);
|
||||
text: 'Fn';
|
||||
padding: (BlInsets all: 5)) ].
|
||||
|
||||
^ verticalContainer asScrollableElement
|
||||
constraintsDo: [ :c |
|
||||
c horizontal fitContent.
|
||||
c vertical matchParent ];
|
||||
background: Color white;
|
||||
aptitude: BrShadowAptitude new
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpTypeSignature >> explainSignature [
|
||||
| mainContainer coderElement leftContainer rightContainer rightContainerLabel leftContainerLabel tooltipsTarget coder elementsContainer editor |
|
||||
mainContainer := BrHorizontalPane new
|
||||
matchParent;
|
||||
padding: (BlInsets all: 5).
|
||||
mainContainer explainer isExplanationHolder: true.
|
||||
|
||||
leftContainer := BrVerticalPane new
|
||||
hFitContent;
|
||||
vMatchParent;
|
||||
padding: (BlInsets all: 5);
|
||||
margin: (BlInsets right: 20).
|
||||
|
||||
rightContainer := BrVerticalPane new
|
||||
matchParent;
|
||||
padding: (BlInsets all: 5).
|
||||
|
||||
tooltipsContainer := BrEditor new
|
||||
text: '' asRopedText;
|
||||
padding: (BlInsets all: 10);
|
||||
margin: (BlInsets
|
||||
top: 10
|
||||
right: 0
|
||||
bottom: 0
|
||||
left: 0);
|
||||
constraintsDo: [ :c | c horizontal matchParent ];
|
||||
visibility: BlVisibility gone;
|
||||
border: (BlBorder paint: BrGlamorousColors textHighlightColor width: 2);
|
||||
aptitude: BrShadowAptitude + BrGlamorousEditorAptitude;
|
||||
vFitContent;
|
||||
background: BrGlamorousColors textHighlightColor.
|
||||
|
||||
tooltipsTarget := BrButton new
|
||||
constraintsDo: [ :c | c ignoreByLayout ];
|
||||
size: 0 @ 0;
|
||||
elevation: (BlRelativeElevation elevation: 10);
|
||||
geometry: BlCircleGeometry new.
|
||||
|
||||
elementsContainer := self elementsList.
|
||||
|
||||
leftContainerLabel := BrLabel new
|
||||
text: ('Type Elements:' asRopedText
|
||||
glamorousRegularFont;
|
||||
foreground: Color gray);
|
||||
aptitude: BrGlamorousLabelAptitude;
|
||||
hFitContent;
|
||||
margin: (BlInsets
|
||||
top: 0
|
||||
right: 0
|
||||
bottom: 5
|
||||
left: 0).
|
||||
rightContainerLabel := BrLabel new
|
||||
text: ('Type:' asRopedText
|
||||
glamorousRegularFont;
|
||||
foreground: Color gray);
|
||||
aptitude: BrGlamorousLabelAptitude;
|
||||
margin: (BlInsets
|
||||
top: 0
|
||||
right: 0
|
||||
bottom: 5
|
||||
left: 5).
|
||||
|
||||
editor := BrEditorElement new
|
||||
constraintsDo: [ :c |
|
||||
c horizontal matchParent.
|
||||
c vertical matchParent ];
|
||||
editor: (BrTextEditor new text: signature value source asRopedText glamorousCodeFont).
|
||||
|
||||
leftContainer addChild: leftContainerLabel.
|
||||
leftContainer addChild: elementsContainer.
|
||||
|
||||
rightContainer addChild: rightContainerLabel.
|
||||
rightContainer addChild: editor.
|
||||
rightContainer addChild: tooltipsContainer.
|
||||
|
||||
mainContainer addChild: leftContainer.
|
||||
mainContainer addChild: rightContainer.
|
||||
|
||||
^ mainContainer
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpTypeSignature >> fromAST: anASTNode [
|
||||
signature := anASTNode
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpTypeSignature >> gtLiveFor: aView [
|
||||
<gtView>
|
||||
^ aView explicit
|
||||
title: 'Signature';
|
||||
priority: 1;
|
||||
stencil: [ self explainSignature ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
CarpTypeSignature >> model: aModel [
|
||||
model := aModel
|
||||
]
|
@@ -3,7 +3,10 @@ Class {
|
||||
#superclass : #GtSourceCoder,
|
||||
#instVars : [
|
||||
'pharoBindings',
|
||||
'carpLinkApplicationStrategy'
|
||||
'carpLinkApplicationStrategy',
|
||||
'exception',
|
||||
'application',
|
||||
'commandFactory'
|
||||
],
|
||||
#category : #'Carp-Coder'
|
||||
}
|
||||
@@ -24,32 +27,43 @@ GtCarpCoderModel >> asCoderViewModel [
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> bindAndExecute: sourceString [
|
||||
"Answer the source code with all declared variables returned in an immediate dictionary"
|
||||
|
||||
<gtIgnoreConstraint: #GtRBAcceptVisitorCalledFromNonVisitingMethods>
|
||||
| carpSource trimmedSource ast varNames lastStatement application commandFactory |
|
||||
|
||||
<remoteDebuggerSignal>
|
||||
| res trimmedSource ast varNames lastStatement carpSource |
|
||||
trimmedSource := SmaCCString on: sourceString trimRight.
|
||||
ast := CarpParser parse: trimmedSource.
|
||||
"The variables to be returned are names that are in pharoBindings"
|
||||
varNames := pharoBindings bindingNames asSet.
|
||||
|
||||
"Assign the final statement to snippetResult"
|
||||
ast := CarpParser parse: trimmedSource. "The variables to be returned are names that are in pharoBindings"
|
||||
varNames := pharoBindings
|
||||
ifNil: [ Set new ]
|
||||
ifNotNil: [ pharoBindings bindingNames asSet ]. "Assign the final statement to snippetResult"
|
||||
lastStatement := ast expressions last.
|
||||
trimmedSource
|
||||
insert: '(defdynamic snippetResult '
|
||||
trimmedSource
|
||||
insert: '(defdynamic snippetResult '
|
||||
at: lastStatement startPosition.
|
||||
varNames add: 'snippetResult'.
|
||||
trimmedSource insert: ')' at: lastStatement stopPosition.
|
||||
varNames add: 'snippetResult'. "Get the final source to execute"
|
||||
carpSource := self
|
||||
sourceFrom: trimmedSource asString
|
||||
returnedVarNames: varNames.
|
||||
res := self bindAndExecuteRaw: sourceString.
|
||||
|
||||
"Get the final source to execute"
|
||||
carpSource := self sourceFrom: trimmedSource asString returnedVarNames: varNames.
|
||||
(res at: #result) = 'success' ifTrue: [ ^ CarpExecutionResult from: res ].
|
||||
exception := PharoLinkRemoteError new
|
||||
application: application;
|
||||
command: commandFactory command;
|
||||
trace: (res at: #value).
|
||||
exception signal
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> bindAndExecuteRaw: sourceString [
|
||||
application := carpLinkApplicationStrategy applicationServer.
|
||||
application isRunning ifFalse: [ application start ].
|
||||
commandFactory := application newCommandFactory.
|
||||
|
||||
^ commandFactory
|
||||
<< carpSource;
|
||||
sendAndWait.
|
||||
|
||||
<< sourceString;
|
||||
sendAndWait
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@@ -63,39 +77,85 @@ GtCarpCoderModel >> computeAst: theSourceString [
|
||||
parseWithErrors: theSourceString
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> exception [
|
||||
^ exception
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> initializeAddOns: addOns [
|
||||
super initializeAddOns: addOns.
|
||||
|
||||
addOns addStyler: (GtCoderAstSmaCCParserStyler new smaccStyler: CarpParser gtStyler).
|
||||
|
||||
|
||||
addOns
|
||||
addMainAction: 'Evaluate' translated
|
||||
icon: BrGlamorousVectorIcons play
|
||||
action: [ :aCoderUIModel :anElement |
|
||||
GtCoderCodeExecutor doIt
|
||||
coderViewModel: aCoderUIModel;
|
||||
element: anElement;
|
||||
execute ]
|
||||
id: GtSourceCoderDoItActionId.
|
||||
addOns
|
||||
addMainAction: 'Inspect' translated
|
||||
icon: BrGlamorousVectorIcons playinspect
|
||||
action: [ :aCoderUIModel :anElement |
|
||||
GtCoderCodeExecutor doItAndGo
|
||||
coderViewModel: aCoderUIModel;
|
||||
element: anElement;
|
||||
execute ]
|
||||
id: GtSourceCoderDoItAndGoActionId.
|
||||
addStyler: (GtCoderAstSmaCCParserStyler new smaccStyler: CarpParser gtStyler).
|
||||
|
||||
application
|
||||
ifNotNil: [ addOns
|
||||
addMainAction: 'Evaluate' translated
|
||||
icon: BrGlamorousVectorIcons play
|
||||
action: [ :aCoderUIModel :anElement |
|
||||
GtCoderCodeExecutor doIt
|
||||
coderViewModel: aCoderUIModel;
|
||||
element: anElement;
|
||||
execute ]
|
||||
id: GtSourceCoderDoItActionId.
|
||||
addOns
|
||||
addMainAction: 'Inspect' translated
|
||||
icon: BrGlamorousVectorIcons playinspect
|
||||
action: [ :aCoderUIModel :anElement |
|
||||
GtCoderCodeExecutor doItAndGo
|
||||
coderViewModel: aCoderUIModel;
|
||||
element: anElement;
|
||||
execute ]
|
||||
id: GtSourceCoderDoItAndGoActionId.
|
||||
addOns
|
||||
addMainAction: 'Expand Macros' translated
|
||||
icon: BrGlamorousVectorIcons repair
|
||||
action: [ :aCoderUIModel :anElement |
|
||||
| source |
|
||||
source := '(expand ''' , sourceCode currentSourceText value text , ')'.
|
||||
anElement phlow
|
||||
spawnObject: ((self bindAndExecute: source) parse view: #gtSourceFor:) ]
|
||||
id: #'source-coder--macro-expand-action'.
|
||||
addOns
|
||||
addMainAction: 'Build and Run' translated
|
||||
icon: BrGlamorousVectorIcons refresh
|
||||
action: [ :aCoderUIModel :anElement |
|
||||
| source |
|
||||
source := '' , sourceCode currentSourceText value text , '(build) (run)'.
|
||||
anElement phlow
|
||||
spawnObject: (CarpCliOutput text: ((self bindAndExecuteRaw: source) at: 'value')) ]
|
||||
id: #'source-coder--build-and-run-action'.
|
||||
addOns
|
||||
addMainAction: 'Infer Type' translated
|
||||
icon: BrGlamorousVectorIcons inspect
|
||||
action: [ :aCoderUIModel :anElement | self inspectTypeSpawningOn: anElement phlow ]
|
||||
id: #'source-coder--type-infer-action' ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> initializeShortcuts: addOns [
|
||||
super initializeShortcuts: addOns.
|
||||
|
||||
addOns
|
||||
addShortcut: GtSourceCoderDoItShortcut new;
|
||||
addShortcut: GtSourceCoderDoItAndInspectShortcut new
|
||||
application
|
||||
ifNotNil: [ addOns
|
||||
addShortcut: GtSourceCoderDoItShortcut new;
|
||||
addShortcut: GtSourceCoderDoItAndInspectShortcut new ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> inspectTypeSpawningOn: aPhlow [
|
||||
| source ast |
|
||||
source := sourceCode currentSourceText value text.
|
||||
ast := CarpParser parse: source.
|
||||
|
||||
(ast expressions size = 1 and: [ ast expressions first isDefinition ])
|
||||
ifTrue: [ self bindAndExecute: source asString.
|
||||
source := ast expressions first definitionVariable value source ].
|
||||
|
||||
source := '(def *type-infer-this* ' , source
|
||||
, ') (defdynamic *type-infer-result* (type *type-infer-this*)) (def *type-infer-this* 0) *type-infer-result*'.
|
||||
aPhlow spawnObject: ((self bindAndExecute: source) parse transformValue: [:aValue | CarpTypeSignature on: aValue expressions first using: self])
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@@ -110,36 +170,18 @@ GtCarpCoderModel >> pharoBindings: anObject [
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> primitiveEvaluate: aSourceString inContext: aGtSourceCoderEvaluationContext onFailDo: anEvaluationFailBlock [
|
||||
| result |
|
||||
|
||||
result := self bindAndExecute: aSourceString.
|
||||
result associationsDo: [ :binding |
|
||||
(pharoBindings bindingOf: binding key asSymbol) value: binding value ].
|
||||
|
||||
^ result
|
||||
at: 'snippetResult'
|
||||
ifAbsent: anEvaluationFailBlock
|
||||
^ (self bindAndExecute: aSourceString) parse
|
||||
transformValue: [ :aValue | aValue expressions first toPharo ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpCoderModel >> sourceFrom: trimmedSourceString returnedVarNames: varNames [
|
||||
"Answer the modified source to return the declared variables"
|
||||
|
||||
^ String streamContents: [ :stream |
|
||||
stream << trimmedSourceString.
|
||||
stream
|
||||
cr
|
||||
<< '{ '.
|
||||
varNames do: [ :varName |
|
||||
stream
|
||||
<< '(quote ';
|
||||
<< varName;
|
||||
<< ') ';
|
||||
<< varName;
|
||||
<< ' ' ].
|
||||
"Answer the variable dictionary as an immediate object"
|
||||
stream
|
||||
<< '(quote carpLinkImmediate) true }' ]
|
||||
^ String
|
||||
streamContents: [ :stream |
|
||||
stream << trimmedSourceString.
|
||||
stream lf << 'snippetResult' ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
|
50
src/Carp/GtCarpIDECoderModel.class.st
Normal file
50
src/Carp/GtCarpIDECoderModel.class.st
Normal file
@@ -0,0 +1,50 @@
|
||||
Class {
|
||||
#name : #GtCarpIDECoderModel,
|
||||
#superclass : #GtCarpNewFunctionCoderModel,
|
||||
#instVars : [
|
||||
'expression'
|
||||
],
|
||||
#category : #'Carp-Coder'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpIDECoderModel >> collapsedTextPromise [
|
||||
^ self expression name name , ' : '
|
||||
, (self bindAndExecute: '(type ' , module name, '.', self expression name name , ')') value
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpIDECoderModel >> expression [
|
||||
^ expression
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpIDECoderModel >> expression: anExpression [
|
||||
expression := anExpression
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpIDECoderModel >> initializeAddOns: addOns [
|
||||
super initializeAddOns: addOns.
|
||||
|
||||
addOns
|
||||
addMainAction: 'Remove' translated
|
||||
icon: BrGlamorousVectorIcons remove
|
||||
action: [ :aCoderUIModel :anElement | self remove ]
|
||||
id: GtMethodCoderSaveActionId
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpIDECoderModel >> remove [
|
||||
module removeExpression: self expression.
|
||||
self bindAndExecute: module toCarp
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpIDECoderModel >> save [
|
||||
module removeExpression: expression.
|
||||
module
|
||||
addExpression: (CarpParser parse: sourceCode availableSource text) intoModel.
|
||||
self bindAndExecute: module toCarp.
|
||||
onSave ifNotNil: [ onSave value ]
|
||||
]
|
40
src/Carp/GtCarpNewFunctionCoderModel.class.st
Normal file
40
src/Carp/GtCarpNewFunctionCoderModel.class.st
Normal file
@@ -0,0 +1,40 @@
|
||||
Class {
|
||||
#name : #GtCarpNewFunctionCoderModel,
|
||||
#superclass : #GtCarpCoderModel,
|
||||
#instVars : [
|
||||
'module',
|
||||
'onSave'
|
||||
],
|
||||
#category : #'Carp-Coder'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpNewFunctionCoderModel >> initializeAddOns: addOns [
|
||||
addOns
|
||||
addStyler: (GtCoderAstSmaCCParserStyler new smaccStyler: CarpParser gtStyler).
|
||||
|
||||
addOns
|
||||
addMainAction: 'Save' translated
|
||||
icon: BrGlamorousVectorIcons accept
|
||||
action: [ :aCoderUIModel :anElement | self save ]
|
||||
id: GtMethodCoderSaveActionId
|
||||
]
|
||||
|
||||
{ #category : #coders }
|
||||
GtCarpNewFunctionCoderModel >> module: aModule [
|
||||
module := aModule
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpNewFunctionCoderModel >> onSave: aBlock [
|
||||
onSave := aBlock
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
GtCarpNewFunctionCoderModel >> save [
|
||||
| expression |
|
||||
expression := (CarpParser parse: sourceCode currentSourceText value text) intoModel.
|
||||
module addExpression: expression.
|
||||
self bindAndExecute: module toCarp.
|
||||
onSave ifNotNil: [ onSave value ]
|
||||
]
|
@@ -9,10 +9,10 @@ LanguageLinkSettings class >> carpDefaultSettings [
|
||||
serverSocketAddress: (LanguageLinkSocketAddress
|
||||
ipOrName: 'localhost' port: (9900 + 99 atRandom));
|
||||
messageBrokerStrategy: LanguageLinkHttpMessageBroker;
|
||||
serverProcessClass: CarpProcess;
|
||||
serverProcessClass: CarpPythonProcess;
|
||||
platform: CarpPlatform new;
|
||||
commandFactoryClass: CarpCommandFactory;
|
||||
commandClass: LanguageLinkCommand;
|
||||
commandClass: CarpCommand;
|
||||
serializerClass: LanguageLinkSerializer;
|
||||
deserializerClass: CarpDeserializer;
|
||||
parserClass: CarpParser;
|
||||
|
@@ -13,9 +13,6 @@ LeCarpApplicationStrategy class >> strategyName [
|
||||
{ #category : #accessing }
|
||||
LeCarpApplicationStrategy >> applicationServer [
|
||||
|
||||
content database isDatabase ifFalse: [ ^ nil ].
|
||||
CarpApplication uniqueInstance ifNil:
|
||||
[ CarpApplication uniqueInstance: (self newCarpApplicationFor: content database) ].
|
||||
^ CarpApplication uniqueInstance
|
||||
]
|
||||
|
||||
@@ -27,31 +24,5 @@ LeCarpApplicationStrategy >> applicationSettings [
|
||||
^ CarpApplication isRunning ifTrue:
|
||||
[ CarpApplication uniqueInstance settings ]
|
||||
ifFalse:
|
||||
[ self updatedSettings: CarpApplication defaultSettings ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
LeCarpApplicationStrategy >> newCarpApplicationFor: aLeDatabase [
|
||||
|
||||
^ CarpApplication new initializeWith:
|
||||
(self updatedSettings: LanguageLinkSettings carpDefaultSettings).
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
LeCarpApplicationStrategy >> updatedSettings: applicationCarpSettings [
|
||||
"Update the supplied settings with the lepiter configuration"
|
||||
| lepiterCarpSettings lepiterDatabase carpDir |
|
||||
|
||||
lepiterDatabase := content database.
|
||||
lepiterCarpSettings := lepiterDatabase properties carpLinkSettings.
|
||||
lepiterCarpSettings directory ifNotNil:
|
||||
[ :relativeDir |
|
||||
carpDir := lepiterDatabase localStoreRootDirectory resolve: relativeDir.
|
||||
applicationCarpSettings workingDirectory: carpDir ].
|
||||
"lepiterCarpSettings carpPath ifNotNil:
|
||||
[ :carpPath | applicationCarpSettings serverExecutable: carpPath ]."
|
||||
applicationCarpSettings serverDebugMode: lepiterCarpSettings serverDebugMode.
|
||||
|
||||
^ applicationCarpSettings
|
||||
[ CarpApplication defaultSettings ]
|
||||
]
|
||||
|
@@ -1,11 +1,11 @@
|
||||
Extension { #name : #ByteString }
|
||||
Extension { #name : #String }
|
||||
|
||||
{ #category : #'*Carp' }
|
||||
ByteString >> asCarpModule [
|
||||
String >> asCarpModule [
|
||||
^ CarpModule named: self
|
||||
]
|
||||
|
||||
{ #category : #'*Carp' }
|
||||
ByteString >> asCarpSymbol [
|
||||
String >> asCarpSymbol [
|
||||
^ CarpSymbol named: self
|
||||
]
|
Reference in New Issue
Block a user