Merge branch 'trunk' of ssh://src.le-moine.org:38172/gwh/rpl.rb into trunk
This commit is contained in:
commit
42244c7106
33 changed files with 150 additions and 118 deletions
|
@ -2,6 +2,10 @@
|
|||
|
||||
https://github.com/louisrubet/rpn/ inspired language in ruby
|
||||
|
||||
To run REPL locally: `ruby -Ilib bin/rpl`
|
||||
|
||||
To run the test suite: `find ./spec/ -name \*.rb -exec ruby -Ilib {} \;`
|
||||
|
||||
# TODO-list
|
||||
* pseudo filesystem: subdir for variables
|
||||
* UI toolkit (based on https://github.com/AndyObtiva/glimmer-dsl-libui ?)
|
||||
|
|
51
bin/rpl
Executable file
51
bin/rpl
Executable file
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'readline'
|
||||
|
||||
require 'rpl'
|
||||
|
||||
class RplRepl
|
||||
def initialize
|
||||
@interpreter = Rpl.new
|
||||
end
|
||||
|
||||
def run
|
||||
Readline.completion_proc = proc do |s|
|
||||
( @interpreter.dictionary.words.keys + @interpreter.dictionary.vars.keys ).grep(/^#{Regexp.escape(s)}/)
|
||||
end
|
||||
Readline.completion_append_character = ' '
|
||||
|
||||
loop do
|
||||
input = Readline.readline( ' ', true )
|
||||
break if input.nil? || input == 'quit'
|
||||
|
||||
pp Readline::HISTORY if input == 'history'
|
||||
|
||||
# Remove blank lines from history
|
||||
Readline::HISTORY.pop if input.empty?
|
||||
|
||||
begin
|
||||
@interpreter.run( input )
|
||||
rescue ArgumentError => e
|
||||
p e
|
||||
end
|
||||
|
||||
print_stack
|
||||
end
|
||||
end
|
||||
|
||||
def format_element( elt )
|
||||
@interpreter.stringify( elt )
|
||||
end
|
||||
|
||||
def print_stack
|
||||
stack_size = @interpreter.stack.size
|
||||
|
||||
@interpreter.stack.each_with_index do |elt, i|
|
||||
puts "#{stack_size - i}: #{format_element( elt )}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RplRepl.new.run
|
43
lib/rpl.rb
Normal file
43
lib/rpl.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rpl/interpreter'
|
||||
|
||||
require 'rpl/core/branch'
|
||||
require 'rpl/core/general'
|
||||
require 'rpl/core/mode'
|
||||
require 'rpl/core/operations'
|
||||
require 'rpl/core/program'
|
||||
require 'rpl/core/stack'
|
||||
require 'rpl/core/store'
|
||||
require 'rpl/core/string'
|
||||
require 'rpl/core/test'
|
||||
require 'rpl/core/time-date'
|
||||
require 'rpl/core/trig'
|
||||
require 'rpl/core/logarithm'
|
||||
require 'rpl/core/filesystem'
|
||||
require 'rpl/core/list'
|
||||
|
||||
class Rpl < Interpreter
|
||||
def initialize( stack = [], dictionary = Dictionary.new )
|
||||
super
|
||||
|
||||
populate_dictionary if @dictionary.words.empty?
|
||||
end
|
||||
|
||||
prepend RplLang::Core::Branch
|
||||
prepend RplLang::Core::FileSystem
|
||||
prepend RplLang::Core::General
|
||||
prepend RplLang::Core::List
|
||||
prepend RplLang::Core::Logarithm
|
||||
prepend RplLang::Core::Mode
|
||||
prepend RplLang::Core::Operations
|
||||
prepend RplLang::Core::Program
|
||||
prepend RplLang::Core::Stack
|
||||
prepend RplLang::Core::Store
|
||||
prepend RplLang::Core::String
|
||||
prepend RplLang::Core::Test
|
||||
prepend RplLang::Core::TimeAndDate
|
||||
prepend RplLang::Core::Trig
|
||||
|
||||
def populate_dictionary; end
|
||||
end
|
|
@ -34,8 +34,7 @@ module RplLang
|
|||
|
||||
run( args[1][:value] )
|
||||
end
|
||||
|
||||
end ) # specific
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['loop'],
|
||||
'Branch',
|
||||
|
@ -49,7 +48,7 @@ module RplLang
|
|||
|
||||
run( args[2][:value] )
|
||||
end
|
||||
end ) # specific
|
||||
end )
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,8 +6,6 @@ module RplLang
|
|||
def populate_dictionary
|
||||
super
|
||||
|
||||
|
||||
# Mode
|
||||
@dictionary.add_word( ['prec'],
|
||||
'Mode',
|
||||
'( a -- ) set precision to a',
|
|
@ -385,7 +385,6 @@ module RplLang
|
|||
# proc do
|
||||
|
||||
# end )
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -124,7 +124,6 @@ module RplLang
|
|||
end
|
||||
|
||||
@stack << args[0]
|
||||
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['rolld'],
|
|
@ -60,7 +60,6 @@ module RplLang
|
|||
« swap »
|
||||
ift
|
||||
over rcl + swap sto' )
|
||||
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['sto-'],
|
||||
|
@ -83,7 +82,6 @@ module RplLang
|
|||
« swap »
|
||||
ift
|
||||
over rcl * swap sto' )
|
||||
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['sto÷', 'sto/'],
|
||||
|
@ -95,7 +93,6 @@ module RplLang
|
|||
« swap »
|
||||
ift
|
||||
over rcl swap / swap sto' )
|
||||
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['sneg'],
|
|
@ -95,7 +95,7 @@ module RplLang
|
|||
end
|
||||
|
||||
@stack << result
|
||||
end ) # specific
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['split'],
|
||||
'String',
|
||||
|
@ -107,7 +107,7 @@ module RplLang
|
|||
@stack << { type: :string,
|
||||
value: elt }
|
||||
end
|
||||
end ) # specific
|
||||
end )
|
||||
end
|
||||
end
|
||||
end
|
|
@ -112,7 +112,7 @@ module RplLang
|
|||
proc do
|
||||
@stack << { type: :boolean,
|
||||
value: true }
|
||||
end ) # specific
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['false'],
|
||||
'Test',
|
||||
|
@ -120,7 +120,7 @@ module RplLang
|
|||
proc do
|
||||
@stack << { type: :boolean,
|
||||
value: false }
|
||||
end ) # specific
|
||||
end )
|
||||
end
|
||||
end
|
||||
end
|
|
@ -63,7 +63,6 @@ module RplLang
|
|||
ift
|
||||
»
|
||||
ifte' )
|
||||
|
||||
end )
|
||||
|
||||
@dictionary.add_word( ['tan'],
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'bigdecimal/math'
|
||||
|
||||
require_relative './dictionary'
|
||||
require 'rpl/dictionary'
|
||||
|
||||
class Interpreter
|
||||
include BigMath
|
33
rpl.gemspec
Normal file
33
rpl.gemspec
Normal file
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = 'rpl'
|
||||
s.version = '0.1.0'
|
||||
s.summary = 'Functional Stack Language'
|
||||
s.description = "A language inspired by HP's RPL and https://github.com/louisrubet/rpn/"
|
||||
s.authors = ['Gwenhael Le Moine']
|
||||
s.email = 'gwenhael@le-moine.org'
|
||||
s.files = ['lib/rpl.rb',
|
||||
'lib/rpl/dictionary.rb',
|
||||
'lib/rpl/interpreter.rb',
|
||||
'lib/rpl/core/branch.rb',
|
||||
'lib/rpl/core/filesystem.rb',
|
||||
'lib/rpl/core/general.rb',
|
||||
'lib/rpl/core/list.rb',
|
||||
'lib/rpl/core/logarithm.rb',
|
||||
'lib/rpl/core/mode.rb',
|
||||
'lib/rpl/core/operations.rb',
|
||||
'lib/rpl/core/program.rb',
|
||||
'lib/rpl/core/stack.rb',
|
||||
'lib/rpl/core/store.rb',
|
||||
'lib/rpl/core/string.rb',
|
||||
'lib/rpl/core/test.rb',
|
||||
'lib/rpl/core/time-date.rb',
|
||||
'lib/rpl/core/trig.rb']
|
||||
s.homepage = 'https://github.com/gwenhael-le-moine/rpl.rb'
|
||||
s.license = 'GPL-3.0'
|
||||
|
||||
s.executables << 'rpl'
|
||||
|
||||
s.required_ruby_version = '~> 2.7'
|
||||
end
|
90
rpl.rb
90
rpl.rb
|
@ -1,90 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'readline'
|
||||
|
||||
require_relative './lib/interpreter'
|
||||
|
||||
require_relative './lib/core/branch'
|
||||
require_relative './lib/core/general'
|
||||
require_relative './lib/core/mode'
|
||||
require_relative './lib/core/operations'
|
||||
require_relative './lib/core/program'
|
||||
require_relative './lib/core/stack'
|
||||
require_relative './lib/core/store'
|
||||
require_relative './lib/core/string'
|
||||
require_relative './lib/core/test'
|
||||
require_relative './lib/core/time-date'
|
||||
require_relative './lib/core/trig'
|
||||
require_relative './lib/core/logarithm'
|
||||
require_relative './lib/core/filesystem'
|
||||
require_relative './lib/core/list'
|
||||
|
||||
class Rpl < Interpreter
|
||||
def initialize( stack = [], dictionary = Dictionary.new )
|
||||
super
|
||||
|
||||
populate_dictionary if @dictionary.words.empty?
|
||||
end
|
||||
|
||||
prepend RplLang::Core::Branch
|
||||
prepend RplLang::Core::FileSystem
|
||||
prepend RplLang::Core::General
|
||||
prepend RplLang::Core::List
|
||||
prepend RplLang::Core::Logarithm
|
||||
prepend RplLang::Core::Mode
|
||||
prepend RplLang::Core::Operations
|
||||
prepend RplLang::Core::Program
|
||||
prepend RplLang::Core::Stack
|
||||
prepend RplLang::Core::Store
|
||||
prepend RplLang::Core::String
|
||||
prepend RplLang::Core::Test
|
||||
prepend RplLang::Core::TimeAndDate
|
||||
prepend RplLang::Core::Trig
|
||||
|
||||
def populate_dictionary; end
|
||||
end
|
||||
|
||||
class RplRepl
|
||||
def initialize
|
||||
@interpreter = Rpl.new
|
||||
end
|
||||
|
||||
def run
|
||||
Readline.completion_proc = proc do |s|
|
||||
Readline::HISTORY.grep(/^#{Regexp.escape(s)}/)
|
||||
end
|
||||
Readline.completion_append_character = ' '
|
||||
|
||||
loop do
|
||||
input = Readline.readline( ' ', true )
|
||||
break if input.nil? || input == 'quit'
|
||||
|
||||
pp Readline::HISTORY if input == 'history'
|
||||
|
||||
# Remove blank lines from history
|
||||
Readline::HISTORY.pop if input.empty?
|
||||
|
||||
begin
|
||||
@interpreter.run( input )
|
||||
rescue ArgumentError => e
|
||||
p e
|
||||
end
|
||||
|
||||
print_stack
|
||||
end
|
||||
end
|
||||
|
||||
def format_element( elt )
|
||||
@interpreter.stringify( elt )
|
||||
end
|
||||
|
||||
def print_stack
|
||||
stack_size = @interpreter.stack.size
|
||||
|
||||
@interpreter.stack.each_with_index do |elt, i|
|
||||
puts "#{stack_size - i}: #{format_element( elt )}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RplRepl.new.run if __FILE__ == $PROGRAM_NAME
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestParser < Test::Unit::TestCase
|
||||
def test_stack_extract
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageBranch < Test::Unit::TestCase
|
||||
def test_loop
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageFileSystem < Test::Unit::TestCase
|
||||
def test_fread
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TesttLanguageOperations < Test::Unit::TestCase
|
||||
def test_add
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageProgram < Test::Unit::TestCase
|
||||
def test_eval
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageStack < Test::Unit::TestCase
|
||||
def test_swap
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageProgram < Test::Unit::TestCase
|
||||
def test_sto
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageString < Test::Unit::TestCase
|
||||
def test_to_string
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageTest < Test::Unit::TestCase
|
||||
def test_greater_than
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestLanguageTimeDate < Test::Unit::TestCase
|
||||
def test_time
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TesttLanguageOperations < Test::Unit::TestCase
|
||||
def test_pi
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
require 'test/unit'
|
||||
|
||||
require_relative '../rpl'
|
||||
require 'rpl'
|
||||
|
||||
class TestParser < Test::Unit::TestCase
|
||||
def test_number
|
||||
|
|
Loading…
Reference in a new issue