new RplGrOb type and related words, plus display management words
This commit is contained in:
parent
422a7828a5
commit
3fa79fe97d
10 changed files with 157 additions and 65 deletions
17
bin/rpl
17
bin/rpl
|
@ -60,7 +60,7 @@ class RplRepl
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
refresh_lcd if @interpreter.show_lcd
|
print_display if @interpreter.show_display
|
||||||
|
|
||||||
print_stack
|
print_stack
|
||||||
rescue Interrupt
|
rescue Interrupt
|
||||||
|
@ -70,13 +70,14 @@ class RplRepl
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def refresh_lcd
|
def print_display
|
||||||
@interpreter.lcd_width.times do |x|
|
puts @interpreter.framebuffer
|
||||||
@interpreter.lcd_height.times do |y|
|
.to_i
|
||||||
putc @interpreter.frame_buffer[ ( y * @interpreter.lcd_height ) + x ].zero? ? '_' : '.'
|
.to_s(2)
|
||||||
end
|
.scan(/.{1,#{@interpreter.display_width}}/)
|
||||||
puts "\n"
|
.join("\n")
|
||||||
end
|
.gsub( '0', '_' )
|
||||||
|
.gsub( '1', '.' )
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_stack
|
def print_stack
|
||||||
|
|
|
@ -49,7 +49,6 @@ class Rpl < Interpreter
|
||||||
end
|
end
|
||||||
|
|
||||||
prepend RplLang::Words::Branch
|
prepend RplLang::Words::Branch
|
||||||
prepend RplLang::Words::Display
|
|
||||||
prepend RplLang::Words::FileSystem
|
prepend RplLang::Words::FileSystem
|
||||||
prepend RplLang::Words::General
|
prepend RplLang::Words::General
|
||||||
prepend RplLang::Words::Graphics
|
prepend RplLang::Words::Graphics
|
||||||
|
|
|
@ -23,6 +23,14 @@ class BitArray
|
||||||
def [](position)
|
def [](position)
|
||||||
@mask[position]
|
@mask[position]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_i
|
||||||
|
@mask.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def from_i( value )
|
||||||
|
@mask = value.to_i
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Interpreter
|
class Interpreter
|
||||||
|
@ -30,30 +38,29 @@ class Interpreter
|
||||||
include Types
|
include Types
|
||||||
|
|
||||||
attr_reader :stack,
|
attr_reader :stack,
|
||||||
:frame_buffer,
|
:framebuffer,
|
||||||
:dictionary,
|
:dictionary,
|
||||||
:version,
|
:version
|
||||||
:lcd_width,
|
|
||||||
:lcd_height
|
|
||||||
|
|
||||||
attr_accessor :show_lcd,
|
attr_accessor :show_display,
|
||||||
|
:display_width,
|
||||||
|
:display_height,
|
||||||
:precision
|
:precision
|
||||||
|
|
||||||
def initialize( stack: [], dictionary: Dictionary.new )
|
def initialize( stack: [], dictionary: Dictionary.new )
|
||||||
@dictionary = dictionary
|
@dictionary = dictionary
|
||||||
@stack = stack
|
@stack = stack
|
||||||
|
|
||||||
initialize_frame_buffer
|
initialize_framebuffer
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize_frame_buffer
|
def initialize_framebuffer
|
||||||
@frame_buffer = BitArray.new
|
@framebuffer = BitArray.new
|
||||||
|
|
||||||
# TODO: make this configurable from rpl?
|
@display_width = 131
|
||||||
@lcd_width = 131
|
@display_height = 64
|
||||||
@lcd_height = 64
|
|
||||||
|
|
||||||
@show_lcd = false
|
@show_display = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def run!( input )
|
def run!( input )
|
||||||
|
|
|
@ -103,6 +103,8 @@ class Parser
|
||||||
Types.new_object( RplString, element )
|
Types.new_object( RplString, element )
|
||||||
elsif RplProgram.can_parse?( element )
|
elsif RplProgram.can_parse?( element )
|
||||||
Types.new_object( RplProgram, element )
|
Types.new_object( RplProgram, element )
|
||||||
|
elsif RplGrOb.can_parse?( element )
|
||||||
|
Types.new_object( RplGrOb, element )
|
||||||
elsif RplName.can_parse?( element )
|
elsif RplName.can_parse?( element )
|
||||||
Types.new_object( RplName, element )
|
Types.new_object( RplName, element )
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ require 'rpl/types/string'
|
||||||
require 'rpl/types/program'
|
require 'rpl/types/program'
|
||||||
require 'rpl/types/numeric'
|
require 'rpl/types/numeric'
|
||||||
require 'rpl/types/complex'
|
require 'rpl/types/complex'
|
||||||
|
require 'rpl/types/grob'
|
||||||
|
|
||||||
module Types
|
module Types
|
||||||
module_function
|
module_function
|
||||||
|
|
39
lib/rpl/types/grob.rb
Normal file
39
lib/rpl/types/grob.rb
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rpl/parser'
|
||||||
|
|
||||||
|
module Types
|
||||||
|
class RplGrOb
|
||||||
|
attr_reader :width,
|
||||||
|
:height,
|
||||||
|
:bits,
|
||||||
|
:value
|
||||||
|
|
||||||
|
def initialize( value )
|
||||||
|
raise RplTypeError unless self.class.can_parse?( value )
|
||||||
|
|
||||||
|
parsed = /^GROB:(?<width>\d+):(?<height>\d+):(?<bits>[0-9a-f]+)$/.match( value )
|
||||||
|
|
||||||
|
@width = parsed[:width].to_i
|
||||||
|
@height = parsed[:height].to_i
|
||||||
|
@bits = parsed[:bits].to_i( 16 )
|
||||||
|
|
||||||
|
@value = [@width, @height, @bits]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"GROB:#{@width}:#{@height}:#{@bits.to_s( 16 )}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_parse?( value )
|
||||||
|
value.instance_of?( String ) && value.match?(/^GROB:\d+:\d+:[0-9a-f]+$/)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==( other )
|
||||||
|
other.class == RplGrOb &&
|
||||||
|
other.width == width &&
|
||||||
|
other.height == height &&
|
||||||
|
other.bits == bits
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rpl/words/branch'
|
require 'rpl/words/branch'
|
||||||
require 'rpl/words/display'
|
|
||||||
require 'rpl/words/general'
|
require 'rpl/words/general'
|
||||||
require 'rpl/words/mode'
|
require 'rpl/words/mode'
|
||||||
require 'rpl/words/operations-reals'
|
require 'rpl/words/operations-reals'
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RplLang
|
|
||||||
module Words
|
|
||||||
module Display
|
|
||||||
include Types
|
|
||||||
|
|
||||||
def populate_dictionary
|
|
||||||
super
|
|
||||||
|
|
||||||
category = 'Display'
|
|
||||||
|
|
||||||
@dictionary.add_word!( ['erase'],
|
|
||||||
category,
|
|
||||||
'( -- ) erase display',
|
|
||||||
proc do
|
|
||||||
initialize_frame_buffer
|
|
||||||
end )
|
|
||||||
|
|
||||||
@dictionary.add_word!( ['display→', 'display->'],
|
|
||||||
category,
|
|
||||||
'( -- pict ) put current display state on stack',
|
|
||||||
proc do
|
|
||||||
@stack << @frame_buffer # FIXME: RplPict type
|
|
||||||
end )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -8,23 +8,94 @@ module RplLang
|
||||||
def populate_dictionary
|
def populate_dictionary
|
||||||
super
|
super
|
||||||
|
|
||||||
category = 'Graphics'
|
category = 'GrOb (Graphic Objects)'
|
||||||
|
|
||||||
@dictionary.add_word!( ['lcdon'],
|
@dictionary.add_word!( ['→grob', '->grob'],
|
||||||
category,
|
category,
|
||||||
'( -- ) display lcd',
|
'( w h d -- g ) make a GrOb from 3 numerics: width, height, data',
|
||||||
proc do
|
proc do
|
||||||
# Sets on a boolean that the REPL will survey and show the Gosu window when true
|
args = stack_extract( [[RplNumeric], [RplNumeric], [RplNumeric]] )
|
||||||
@show_lcd = true
|
|
||||||
|
@stack << RplGrOb.new( "GROB:#{args[2].value.to_i}:#{args[1].value.to_i}:#{args[0].value.to_i.to_s( 16 )}" )
|
||||||
|
end )
|
||||||
|
@dictionary.add_word!( ['grob→', 'grob->'],
|
||||||
|
category,
|
||||||
|
'( g -- w h d ) split a GrOb into its 3 basic numerics',
|
||||||
|
proc do
|
||||||
|
args = stack_extract( [[RplGrOb]] )
|
||||||
|
|
||||||
|
@stack << RplNumeric.new( args[0].width )
|
||||||
|
@stack << RplNumeric.new( args[0].height )
|
||||||
|
@stack << RplNumeric.new( args[0].bits, 16 )
|
||||||
|
end )
|
||||||
|
@dictionary.add_word!( ['grob2asciiart'],
|
||||||
|
category,
|
||||||
|
'( g -- s ) render a GrOb as a string',
|
||||||
|
proc do
|
||||||
|
args = stack_extract( [[RplGrOb]] )
|
||||||
|
|
||||||
|
@stack << RplString.new( "\"#{args[0].bits.to_s(2).scan(/.{1,#{args[0].width}}/).join("\n")}\"" )
|
||||||
end )
|
end )
|
||||||
|
|
||||||
@dictionary.add_word!( ['lcdoff'],
|
category = 'Display management and manipulation'
|
||||||
|
|
||||||
|
@dictionary.add_word!( ['displayon'],
|
||||||
category,
|
category,
|
||||||
'( -- ) hide lcd',
|
'( -- ) display display',
|
||||||
proc do
|
proc do
|
||||||
# Sets on a boolean that the REPL will survey and hide the Gosu window when false
|
@show_display = true
|
||||||
@show_lcd = false
|
|
||||||
end )
|
end )
|
||||||
|
@dictionary.add_word!( ['displayoff'],
|
||||||
|
category,
|
||||||
|
'( -- ) hide display',
|
||||||
|
proc do
|
||||||
|
@show_display = false
|
||||||
|
end )
|
||||||
|
|
||||||
|
@dictionary.add_word!( ['displaywidth→', 'displaywidth->'],
|
||||||
|
category,
|
||||||
|
'( -- i ) put framebuffer\'s width on stack',
|
||||||
|
proc do
|
||||||
|
@stack << RplNumeric.new( @display_width.to_i )
|
||||||
|
end )
|
||||||
|
@dictionary.add_word!( ['displayheight→', 'displayheight->'],
|
||||||
|
category,
|
||||||
|
'( -- i ) put framebuffer\'s height on stack',
|
||||||
|
proc do
|
||||||
|
@stack << RplNumeric.new( @display_height.to_i )
|
||||||
|
end )
|
||||||
|
|
||||||
|
@dictionary.add_word!( ['→displaywidth', '->displaywidth'],
|
||||||
|
category,
|
||||||
|
'( i -- ) set framebuffer\'s width',
|
||||||
|
proc do
|
||||||
|
args = stack_extract( [[RplNumeric]] )
|
||||||
|
|
||||||
|
@display_width = args[0].value.to_i
|
||||||
|
end )
|
||||||
|
@dictionary.add_word!( ['→displayheight', '->displayheight'],
|
||||||
|
category,
|
||||||
|
'( i -- ) set framebuffer\'s height',
|
||||||
|
proc do
|
||||||
|
args = stack_extract( [[RplNumeric]] )
|
||||||
|
|
||||||
|
@display_height = args[0].value.to_i
|
||||||
|
end )
|
||||||
|
|
||||||
|
@dictionary.add_word!( ['display→', 'display->'],
|
||||||
|
category,
|
||||||
|
'( -- g ) export framebuffer to GrOb',
|
||||||
|
proc do
|
||||||
|
@stack << RplGrOb.new( "GROB:#{@display_width}:#{@display_height}:#{@framebuffer.to_i.to_s( 16 )}" )
|
||||||
|
end )
|
||||||
|
# @dictionary.add_word!( ['→display', '->display'],
|
||||||
|
# category,
|
||||||
|
# '( g -- ) import GrOb into framebuffer',
|
||||||
|
# proc do
|
||||||
|
# args = stack_extract( [[RplNumeric]] )
|
||||||
|
|
||||||
|
# @framebuffer = args[0].value.to_i
|
||||||
|
# end )
|
||||||
|
|
||||||
@dictionary.add_word!( ['pixon'],
|
@dictionary.add_word!( ['pixon'],
|
||||||
category,
|
category,
|
||||||
|
@ -32,11 +103,10 @@ module RplLang
|
||||||
proc do
|
proc do
|
||||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||||
|
|
||||||
puts "DEBUG: turn on pixel(x: #{args[1].value}, y: #{args[0].value})"
|
|
||||||
x = args[1].value.to_i
|
x = args[1].value.to_i
|
||||||
y = args[0].value.to_i
|
y = args[0].value.to_i
|
||||||
|
|
||||||
@frame_buffer[ ( y * @lcd_height ) + x ] = 1
|
@framebuffer[ ( y * @display_height ) + x ] = 1
|
||||||
end )
|
end )
|
||||||
@dictionary.add_word!( ['pixoff'],
|
@dictionary.add_word!( ['pixoff'],
|
||||||
category,
|
category,
|
||||||
|
@ -44,7 +114,10 @@ module RplLang
|
||||||
proc do
|
proc do
|
||||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||||
|
|
||||||
puts "DEBUG: turn off pixel(x: #{args[1].value}, y: #{args[0].value})"
|
x = args[1].value.to_i
|
||||||
|
y = args[0].value.to_i
|
||||||
|
|
||||||
|
@framebuffer[ ( y * @display_height ) + x ] = 0
|
||||||
end )
|
end )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -84,8 +84,8 @@ module RplLang
|
||||||
category,
|
category,
|
||||||
'() print internal state of framebuffer',
|
'() print internal state of framebuffer',
|
||||||
proc do
|
proc do
|
||||||
pp @show_lcd
|
pp @show_display
|
||||||
pp @frame_buffer
|
pp @framebuffer
|
||||||
end )
|
end )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue