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
|
||||
|
||||
refresh_lcd if @interpreter.show_lcd
|
||||
print_display if @interpreter.show_display
|
||||
|
||||
print_stack
|
||||
rescue Interrupt
|
||||
|
@ -70,13 +70,14 @@ class RplRepl
|
|||
end
|
||||
end
|
||||
|
||||
def refresh_lcd
|
||||
@interpreter.lcd_width.times do |x|
|
||||
@interpreter.lcd_height.times do |y|
|
||||
putc @interpreter.frame_buffer[ ( y * @interpreter.lcd_height ) + x ].zero? ? '_' : '.'
|
||||
end
|
||||
puts "\n"
|
||||
end
|
||||
def print_display
|
||||
puts @interpreter.framebuffer
|
||||
.to_i
|
||||
.to_s(2)
|
||||
.scan(/.{1,#{@interpreter.display_width}}/)
|
||||
.join("\n")
|
||||
.gsub( '0', '_' )
|
||||
.gsub( '1', '.' )
|
||||
end
|
||||
|
||||
def print_stack
|
||||
|
|
|
@ -49,7 +49,6 @@ class Rpl < Interpreter
|
|||
end
|
||||
|
||||
prepend RplLang::Words::Branch
|
||||
prepend RplLang::Words::Display
|
||||
prepend RplLang::Words::FileSystem
|
||||
prepend RplLang::Words::General
|
||||
prepend RplLang::Words::Graphics
|
||||
|
|
|
@ -23,6 +23,14 @@ class BitArray
|
|||
def [](position)
|
||||
@mask[position]
|
||||
end
|
||||
|
||||
def to_i
|
||||
@mask.to_i
|
||||
end
|
||||
|
||||
def from_i( value )
|
||||
@mask = value.to_i
|
||||
end
|
||||
end
|
||||
|
||||
class Interpreter
|
||||
|
@ -30,30 +38,29 @@ class Interpreter
|
|||
include Types
|
||||
|
||||
attr_reader :stack,
|
||||
:frame_buffer,
|
||||
:framebuffer,
|
||||
:dictionary,
|
||||
:version,
|
||||
:lcd_width,
|
||||
:lcd_height
|
||||
:version
|
||||
|
||||
attr_accessor :show_lcd,
|
||||
attr_accessor :show_display,
|
||||
:display_width,
|
||||
:display_height,
|
||||
:precision
|
||||
|
||||
def initialize( stack: [], dictionary: Dictionary.new )
|
||||
@dictionary = dictionary
|
||||
@stack = stack
|
||||
|
||||
initialize_frame_buffer
|
||||
initialize_framebuffer
|
||||
end
|
||||
|
||||
def initialize_frame_buffer
|
||||
@frame_buffer = BitArray.new
|
||||
def initialize_framebuffer
|
||||
@framebuffer = BitArray.new
|
||||
|
||||
# TODO: make this configurable from rpl?
|
||||
@lcd_width = 131
|
||||
@lcd_height = 64
|
||||
@display_width = 131
|
||||
@display_height = 64
|
||||
|
||||
@show_lcd = false
|
||||
@show_display = false
|
||||
end
|
||||
|
||||
def run!( input )
|
||||
|
|
|
@ -103,6 +103,8 @@ class Parser
|
|||
Types.new_object( RplString, element )
|
||||
elsif RplProgram.can_parse?( element )
|
||||
Types.new_object( RplProgram, element )
|
||||
elsif RplGrOb.can_parse?( element )
|
||||
Types.new_object( RplGrOb, element )
|
||||
elsif RplName.can_parse?( element )
|
||||
Types.new_object( RplName, element )
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ require 'rpl/types/string'
|
|||
require 'rpl/types/program'
|
||||
require 'rpl/types/numeric'
|
||||
require 'rpl/types/complex'
|
||||
require 'rpl/types/grob'
|
||||
|
||||
module Types
|
||||
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
|
||||
|
||||
require 'rpl/words/branch'
|
||||
require 'rpl/words/display'
|
||||
require 'rpl/words/general'
|
||||
require 'rpl/words/mode'
|
||||
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
|
||||
super
|
||||
|
||||
category = 'Graphics'
|
||||
category = 'GrOb (Graphic Objects)'
|
||||
|
||||
@dictionary.add_word!( ['lcdon'],
|
||||
@dictionary.add_word!( ['→grob', '->grob'],
|
||||
category,
|
||||
'( -- ) display lcd',
|
||||
'( w h d -- g ) make a GrOb from 3 numerics: width, height, data',
|
||||
proc do
|
||||
# Sets on a boolean that the REPL will survey and show the Gosu window when true
|
||||
@show_lcd = true
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric], [RplNumeric]] )
|
||||
|
||||
@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 )
|
||||
|
||||
@dictionary.add_word!( ['lcdoff'],
|
||||
category = 'Display management and manipulation'
|
||||
|
||||
@dictionary.add_word!( ['displayon'],
|
||||
category,
|
||||
'( -- ) hide lcd',
|
||||
'( -- ) display display',
|
||||
proc do
|
||||
# Sets on a boolean that the REPL will survey and hide the Gosu window when false
|
||||
@show_lcd = false
|
||||
@show_display = true
|
||||
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'],
|
||||
category,
|
||||
|
@ -32,11 +103,10 @@ module RplLang
|
|||
proc do
|
||||
args = stack_extract( [[RplNumeric], [RplNumeric]] )
|
||||
|
||||
puts "DEBUG: turn on pixel(x: #{args[1].value}, y: #{args[0].value})"
|
||||
x = args[1].value.to_i
|
||||
y = args[0].value.to_i
|
||||
|
||||
@frame_buffer[ ( y * @lcd_height ) + x ] = 1
|
||||
@framebuffer[ ( y * @display_height ) + x ] = 1
|
||||
end )
|
||||
@dictionary.add_word!( ['pixoff'],
|
||||
category,
|
||||
|
@ -44,7 +114,10 @@ module RplLang
|
|||
proc do
|
||||
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
|
||||
|
|
|
@ -84,8 +84,8 @@ module RplLang
|
|||
category,
|
||||
'() print internal state of framebuffer',
|
||||
proc do
|
||||
pp @show_lcd
|
||||
pp @frame_buffer
|
||||
pp @show_display
|
||||
pp @framebuffer
|
||||
end )
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue