rename phisol to soml
This commit is contained in:
parent
991cc0519f
commit
e0c5bc4c11
18
README.md
18
README.md
@ -9,9 +9,9 @@ Salama is about native code generation in and of ruby.
|
||||
|
||||
It is probably best to read the [The Book](http://dancinglightning.gitbooks.io/the-object-machine/content/) first.
|
||||
|
||||
The current third rewrite adds a system language, with the idea of compiling ruby to that language, Phisol.
|
||||
The original ruby parser has been remodeled to parse Phisol and later we will use whitequarks
|
||||
parser to parse ruby. Then it will be ruby --> Phisol --> assembler --> binary .
|
||||
The current third rewrite adds a system language, with the idea of compiling ruby to that language, Soml.
|
||||
The original ruby parser has been remodeled to parse Soml and later we will use whitequarks
|
||||
parser to parse ruby. Then it will be ruby --> Soml --> assembler --> binary .
|
||||
|
||||
|
||||
## Done
|
||||
@ -69,11 +69,11 @@ As said, "Hello world" comes out and does use syscall 4.
|
||||
Also the program stops by syscall exit.
|
||||
The full list is on the net and involves mostly just work.
|
||||
|
||||
### Parse Phisol
|
||||
### Parse Soml
|
||||
|
||||
Parse Phisol, using Parslet. This has been separated out as it's own gem, [salama-reader](https://github.com/salama/salama-reader).
|
||||
Parse Soml, using Parslet. This has been separated out as it's own gem, [salama-reader](https://github.com/salama/salama-reader).
|
||||
|
||||
Phisol is now fully typed (all variables, arguments and return). Also it has statements, unlike ruby
|
||||
Soml is now fully typed (all variables, arguments and return). Also it has statements, unlike ruby
|
||||
where everything is an statements. Statements have no value. Otherwise it is quite basic, and
|
||||
it's main purpose is to have an oo system language to compile to.
|
||||
|
||||
@ -108,11 +108,11 @@ exchange format, have the core read that, and use the mechanism to achieve langu
|
||||
|
||||
## Status
|
||||
|
||||
Currently all the work is on the Phisol front. Also documenting the *small* change of a new language.
|
||||
Currently all the work is on the Soml front. Also documenting the *small* change of a new language.
|
||||
|
||||
I'll do some simple string and fibo examples in Phisol next.
|
||||
I'll do some simple string and fibo examples in Soml next.
|
||||
|
||||
Next will be the multiple return feature and then to try to compile ruby to Phisol.
|
||||
Next will be the multiple return feature and then to try to compile ruby to Soml.
|
||||
|
||||
## Future
|
||||
|
||||
|
@ -1,7 +1,15 @@
|
||||
## Notice of change
|
||||
|
||||
The stuff below, like the whole of Parfait, was written before soml. Ie before there was a seperate
|
||||
language to compile a higher language to. Soml is not so dynamic, could do without much of the
|
||||
ObjectSpace that is the core of Parfait.
|
||||
|
||||
So things will change. How will become clear when soml is finished.
|
||||
|
||||
### Parfait: a thin layer
|
||||
|
||||
Parfait is the run-time of the **vm**.
|
||||
To be more precise, it is that part of the run-time needed to boot ruby.
|
||||
To be more precise, it is that part of the run-time needed to boot soml.
|
||||
|
||||
The run-time needs to contain quite a lot of functionality for a dynamic system.
|
||||
And a large part of that functionality must actually be used at compile time too.
|
||||
@ -10,7 +18,7 @@ We reuse the Parfait code at compile-time, to create the data for the compiled v
|
||||
To do this the vm (re) defines the object memory (in parfait_adapter).
|
||||
|
||||
To do the actual compiling we parse and compile the parfait code and inline it to
|
||||
appropriate places (ie send, get_instance_variable etc). We have to inline to avoid recursion.
|
||||
appropriate places.
|
||||
|
||||
A work in progress that started from here : http://salama.github.io/2014/06/10/more-clarity.html
|
||||
went on here http://salama.github.io/2014/07/05/layers-vs-passes.html
|
||||
@ -25,31 +33,9 @@ It's too simple: just slips off the mind like a fish into water.
|
||||
Parfait has a brother, the Builtin module. Builtin contains everything that can not be coded in ruby,
|
||||
but we still need (things like List access).
|
||||
|
||||
#### Example: Message send
|
||||
|
||||
It felt a little stupid that it took me so long to notice that sending a message is very closely
|
||||
related to the existing ruby method Object.send
|
||||
|
||||
Off course Object.send takes symbol and the arguments and has the receiver, so all the elements of our
|
||||
Message are there. And the process that Object.send needs to do is exactly that:
|
||||
send that message, ie find the correct method according to the old walk up the inheritance tree rules and dispatch it.
|
||||
|
||||
And as all this happens at runtime, "all" we have to do is code this logic. And since it is at runtime,
|
||||
we can do it in ruby (as i said, this get's compiled and run, just like the program).
|
||||
|
||||
But what about the infinite loop problem:
|
||||
|
||||
There was a little step left out: Off course the method gets compiled at compile-time and so
|
||||
we don't just blindly dispatch: we catch the simple cases that we know about:
|
||||
layout, type instance variables and compile time known functions.
|
||||
Part of those are some that we just don't allow to be overridden.
|
||||
|
||||
Also what in ruby is object.send is Message.send in salama, as it is the message we are sending and
|
||||
which defines all the data we need (not the object). The object receives, it does not send.
|
||||
|
||||
### Vm vs language- core
|
||||
|
||||
Parfait is not the language (ie ruby) core library. Core library functionality differs between
|
||||
Parfait is not the language core library. Core library functionality differs between
|
||||
languages and so the language core lib must be on top of the vm parfait.
|
||||
|
||||
To make this point clear, i have started using different names for the core classes. Hopefully
|
||||
@ -57,8 +43,3 @@ more sensible ones, ie List instead of Array, Dictionary instead of Hash.
|
||||
|
||||
Also Parfait is meant to be as thin as humanly possibly, so extra (nice to have) functionality
|
||||
will be in future modules.
|
||||
|
||||
So the Namespace of the Runtime is actually Parfait (not nothing as in ruby).
|
||||
Only in the require does one later have to be clever and see which vm one is running in and either
|
||||
require or not. Maybe one doesn't even have to be so clever, we'll see (as requiring an existing
|
||||
module should result in noop)
|
||||
|
@ -5,21 +5,12 @@
|
||||
# It allows for access to those variables basically
|
||||
|
||||
# A Message and a Frame make up the two sides of message passing:
|
||||
# A Message (see details there) is created by the sender and control is transferred
|
||||
# A Message (see details there) is created by the caller and control is transferred
|
||||
# A Frame is created by the receiver
|
||||
# PS: it turns out that both messages and frames are created at compile, not run-time, and
|
||||
# just constantly reused. Each message has a frame object ready and ist also linked
|
||||
# to the next message.
|
||||
# The better way to say above is that a messages is *used* by the caller, and a frame by the callee.
|
||||
|
||||
# In static languages these two objects are one, because the method is known at compile time.
|
||||
# In that case the whole frame is usually on the stack, for leaves even omitted and all data is
|
||||
# held in registers
|
||||
#
|
||||
# In a dynamic language the method is dynamically resolved, and so the size of the frame is not
|
||||
# know to the caller
|
||||
# Also exceptions (with the possibility of retry) and the idea of being able to take and store
|
||||
# bindings make it, to say the very least, unsensibly tricky to store them on the stack. So we don't.
|
||||
# The better way to say above is that a message is *used* by the caller, and a frame by the callee.
|
||||
|
||||
# Also at runtime Messages and Frames remain completely "normal" objects. Ie have layouts and so on.
|
||||
# Which resolves the dichotomy of objects on the stack or heap. Sama sama.
|
||||
|
@ -5,7 +5,7 @@ require "register/positioned"
|
||||
require "register/padding"
|
||||
require "register/parfait_adapter"
|
||||
|
||||
require "phisol/compiler"
|
||||
require "soml/compiler"
|
||||
require "register/method_source"
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@ The RegisterMachine, is an abstract machine with registers. Think of it as an ar
|
||||
normal instruction names. It is not however an abstraction of existing hardware, but only
|
||||
of that subset that we need.
|
||||
|
||||
Our primary objective is to compile Phisol to this level, so the register machine has:
|
||||
Our primary objective is to compile Soml to this level, so the register machine has:
|
||||
- object access instructions
|
||||
- object load
|
||||
- object oriented call semantics
|
||||
|
@ -17,8 +17,8 @@ Slightly more here : http://salama.github.io/2014/06/10/more-clarity.html (then
|
||||
|
||||
The Builtin module is scattered into several files, but that is just so the file doesn't get too long.
|
||||
|
||||
Note: This is about to change slightly with the arrival of Phisol. Phisol is a lower level function,
|
||||
Note: This is about to change slightly with the arrival of Soml. Soml is a lower level function,
|
||||
and as such there is not much that we need that can not be expressed in it. My current thinking
|
||||
is that i can code anything in Phisol and will only need the Phisol instruction set.
|
||||
is that i can code anything in Soml and will only need the Soml instruction set.
|
||||
So this whole Builtin approach may blow over in the next months. It had already become clear that
|
||||
mostly this was going to be about memory access, which in Phisol is part of the language.
|
||||
mostly this was going to be about memory access, which in Soml is part of the language.
|
||||
|
@ -128,7 +128,7 @@ module Register
|
||||
syntax = @parser.parse_with_debug(bytes)
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
#puts parts.inspect
|
||||
Phisol::Compiler.compile( parts )
|
||||
Soml::Compiler.compile( parts )
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
class Compiler < AST::Processor
|
||||
|
||||
def initialize()
|
@ -23,7 +23,7 @@ The compiler has a method for each type for ast, named along on_xxx with xxx as
|
||||
|
||||
#### Compiler holds scope
|
||||
|
||||
The Compiler instance can hold arbitrary scope needed during the compilation. Since we compile Phisol
|
||||
The Compiler instance can hold arbitrary scope needed during the compilation. Since we compile Soml
|
||||
(a static language) things have become more simple.
|
||||
|
||||
A class statement sets the current @clazz scope , a method definition the @method.
|
||||
@ -45,22 +45,13 @@ The general structure of the instructions is a graph
|
||||
Since the machine is virtual, we have to define it, and since it is oo we define it in objects.
|
||||
|
||||
Also it is important to define how instructions operate, which is is in a physical machine would
|
||||
be by changing the contents of registers or some stack.
|
||||
be by changing the contents of registers or some stack.
|
||||
|
||||
Our machine is not a register machine, but an object machine: it operates directly on objects and
|
||||
also has no separate stack, only objects. There are a number of objects which are accessible,
|
||||
and one can think of these (their addresses) as register contents.
|
||||
(And one wouldn't be far off as that is the implementation.)
|
||||
also has no separate stack, only objects. There is only one object which is accessible,
|
||||
basically meaning pinned to a register, the Message.
|
||||
|
||||
The objects the machine works on are:
|
||||
|
||||
- Message
|
||||
- Frame
|
||||
- Self
|
||||
- NewMessage
|
||||
|
||||
and working on means, these are the only objects which the machine accesses.
|
||||
Ie all others would have to be moved first.
|
||||
One can think of the Message as an oo replacement of the stack.
|
||||
|
||||
When a Method needs to make a call, it creates a NewMessage object.
|
||||
Messages contain return addresses (yes, plural) and arguments.
|
||||
@ -69,10 +60,10 @@ The important thing here is that Messages and Frames are normal objects.
|
||||
|
||||
### Distinctly future proof
|
||||
|
||||
Phisol is designed to be used as an implementation language for a higher oo language. Some, or
|
||||
Soml is designed to be used as an implementation language for a higher oo language. Some, or
|
||||
even many, features may not make sense on their own. But these features, like several return
|
||||
addresses, are important to implement the higher language.
|
||||
|
||||
In fact, Phisol's main purpose is not even to be written. The main purpose is to have a language to
|
||||
In fact, Soml's main purpose is not even to be written. The main purpose is to have a language to
|
||||
compile ruby to. In the same way that the assembler layer in salama is not designed to be written,
|
||||
we just need it to create our layers.
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_assignment statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
# collection of the simple ones, int and strings and such
|
||||
|
||||
Compiler.class_eval do
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_call statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_class_field statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_class statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
# attr_reader :values
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_field_access statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
include AST::Sexp
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_function statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
# if - attr_reader :cond, :if_true, :if_false
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
# attr_reader :name
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_operator_value statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
# return attr_reader :statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_statements statement
|
@ -1,4 +1,4 @@
|
||||
module Phisol
|
||||
module Soml
|
||||
Compiler.class_eval do
|
||||
|
||||
def on_while_statement statement
|
@ -13,7 +13,7 @@ module Register
|
||||
# derived classes are Boot/Meta Class and StringConstant
|
||||
class ObjectConstant < Constant
|
||||
# def type
|
||||
# Phisol::Reference
|
||||
# Soml::Reference
|
||||
# end
|
||||
def clazz
|
||||
raise "abstract #{self}"
|
||||
|
@ -1,7 +1,7 @@
|
||||
require_relative '../../helper'
|
||||
require 'parslet/convenience'
|
||||
|
||||
Phisol::Compiler.class_eval do
|
||||
Soml::Compiler.class_eval do
|
||||
def set_main main
|
||||
@clazz = Register.machine.space.get_class_by_name :Object
|
||||
@method = main
|
||||
@ -21,7 +21,7 @@ module CompilerHelper
|
||||
syntax = parser.parse_with_debug(@string_input)
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
#puts parts.inspect
|
||||
compiler = Phisol::Compiler.new
|
||||
compiler = Soml::Compiler.new
|
||||
set_main(compiler)
|
||||
produced = compiler.process( parts )
|
||||
assert @output , "No output given"
|
||||
|
@ -18,7 +18,7 @@ class AddTest < MiniTest::Test
|
||||
s(:int, 5),
|
||||
s(:int, 7)))))))
|
||||
|
||||
Phisol::Compiler.compile( code )
|
||||
Soml::Compiler.compile( code )
|
||||
machine.collect
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Register.machine.init
|
||||
|
@ -24,10 +24,10 @@ HERE
|
||||
syntax = Parser::Salama.new.parse_with_debug(@string_input)
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
#puts parts.inspect
|
||||
Phisol::Compiler.compile( parts )
|
||||
Soml::Compiler.compile( parts )
|
||||
machine.collect
|
||||
# statements = Register.machine.boot.parse_and_compile @string_input
|
||||
# Phisol::Compiler.compile( statements , Register.machine.space.get_main )
|
||||
# Soml::Compiler.compile( statements , Register.machine.space.get_main )
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Register.machine.init
|
||||
#show_ticks # get output of what is
|
||||
|
@ -52,10 +52,10 @@ HERE
|
||||
syntax = Parser::Salama.new.parse_with_debug(@string_input)
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
#puts parts.inspect
|
||||
Phisol::Compiler.compile( parts )
|
||||
Soml::Compiler.compile( parts )
|
||||
machine.collect
|
||||
# statements = Register.machine.boot.parse_and_compile @string_input
|
||||
# Phisol::Compiler.compile( statements , Register.machine.space.get_main )
|
||||
# Soml::Compiler.compile( statements , Register.machine.space.get_main )
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Register.machine.init
|
||||
#show_ticks # get output of what is
|
||||
|
@ -18,7 +18,7 @@ class TestPuts < MiniTest::Test
|
||||
s(:receiver,
|
||||
s(:string, "Hello again")))))))
|
||||
|
||||
Phisol::Compiler.compile( code )
|
||||
Soml::Compiler.compile( code )
|
||||
machine.collect
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Register.machine.init
|
||||
|
Loading…
Reference in New Issue
Block a user