|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
# ==============================================================================
#
# RubyFORTH -- Copyright (C) 2007-8, Marc Simpson (GPL).
#
# File IO.
#
# ==============================================================================
require 'kernel.rb'
# --[ File Inclusion ]----------------------------------------------------------
$included = {}
def root_filename(filename)
return $rubyforth_root + "/" + filename
end
def _forth_include(filename, root)
begin
f = File.open(filename)
f.each do |line|
$current_line = line
code $current_line
end
$included[filename] = true
rescue
if ! root
return _forth_include(root_filename(filename), true)
end
puts "Error: could not include Forth file '#{filename}'"
throw("toplevel")
end
end
def forth_include
forth # ensure we're in the forth context
filename = parse_word
line = $current_line # altered by _forth_include
_forth_include(filename, false)
$current_line = line # restore
forth
end
def forth_included(filename) # is filename already included?
inc1 = $included[filename]
inc2 = $included[root_filename(filename)]
return inc1 | inc2
end
def forth_needs # include a file unless already included.
forth # ensure we're in the forth context
filename = parse_word
line = $current_line # altered by _forth_include
already = forth_included(filename)
if ! already
_forth_include(filename, false)
end
$current_line = line # restore
forth
end
def _ruby_include(filename, root)
begin
require(filename)
rescue LoadError
if ! root
return _ruby_include(root_filename(filename), true)
end
puts "Error: could not load Ruby file"
puts "Ruby reported the following error: '#{$!}'"
throw("toplevel")
end
end
def ruby_include
filename = parse_word
_ruby_include(filename, false)
end
prim "needs" , "forth_needs"
prim "include" , "forth_include"
prim "included?" , "push(forth_flag(forth_included(pop)))"
prim "ruby-include" , "ruby_include"
# --[ File Access ]-------------------------------------------------------------
#
# The problem: we want to use file descriptors from Forth to allow for simple
# numerical referencing. Ruby uses File instances.
#
# The solution: file descriptors are indices into the $file array; elements in
# this array are File instances.
$file = Array.new(128)
def forth_open # ( filename$ mode$ -- fd )
mode = pop
name = pop
begin
inst = File.open(name, mode)
fd = inst.to_i
$file[fd]=inst
push(fd)
rescue
puts "Error: could not open file: '#{name}' with mode: '#{mode}'"
end
end
prim "open" , "forth_open"
prim "read" , "swap ; push($file[pop].read(pop))"
prim "eof?" , "push(forth_flag($file[pop].eof?))"
prim "seek" , "swap ; $file[pop].seek(pop, IO::SEEK_SET)"
prim "write" , "$file[pop].print(pop)"
prim "close" , "$file[pop].close"
prim "position" , "push($file[pop].pos)"
prim "readline" , "push($file[pop].gets)"