diff --git a/spec/myst/file_spec.mt b/spec/myst/file_spec.mt new file mode 100644 index 0000000..8d91d40 --- /dev/null +++ b/spec/myst/file_spec.mt @@ -0,0 +1,28 @@ +require "stdlib/spec.mt" + + +describe("File#open") do + it("returns a new File instance for the given file") do + file = File.open("spec/support/misc/fixed_size_file.txt", "r") + + assert(file.type.to_s == "File") + end + + it("defaults to 'read' mode if no mode is given") do + file = File.open("spec/support/misc/fixed_size_file.txt") + assert(file.mode == "r") + end +end + +describe("File#close") do + # TODO: test that the file descriptor is properly closed. +end + +describe("File#size") do + it("returns an Integer of the number of bytes the file contains") do + # `fixed_size_file.txt` should always be 63 bytes in size. + file = %File{"spec/support/misc/fixed_size_file.txt", "r"} + + assert(file.size == 63) + end +end diff --git a/spec/myst/spec.mt b/spec/myst/spec.mt index 15ee250..206ed2b 100644 --- a/spec/myst/spec.mt +++ b/spec/myst/spec.mt @@ -7,6 +7,7 @@ include Spec.DSL # files under this directory. require "./boolean_spec.mt" require "./enumerable_spec.mt" +require "./file_spec.mt" require "./float_spec.mt" require "./integer_spec.mt" require "./io_spec.mt" diff --git a/spec/support/misc/fixed_size_file.txt b/spec/support/misc/fixed_size_file.txt new file mode 100644 index 0000000..78835db --- /dev/null +++ b/spec/support/misc/fixed_size_file.txt @@ -0,0 +1 @@ +This file has a fixed size of 63 bytes. Do not edit this file! diff --git a/src/myst/interpreter/native_lib/file.cr b/src/myst/interpreter/native_lib/file.cr index d390f2d..3999eca 100644 --- a/src/myst/interpreter/native_lib/file.cr +++ b/src/myst/interpreter/native_lib/file.cr @@ -4,18 +4,25 @@ module Myst file = File.open(name.value, mode.value) @fd_pool[file.fd] = file - this.ivars["fd"] = TInteger.new(file.fd.to_i64) + this.ivars["@fd"] = TInteger.new(file.fd.to_i64) + this.ivars["@mode"] = mode this end NativeLib.method :file_close, TInstance do - fd = this.ivars["fd"].as(TInteger) + fd = this.ivars["@fd"].as(TInteger) file = @fd_pool[fd.value] file.close @fd_pool.delete(fd.value) TNil.new end + NativeLib.method :file_size, TInstance do + fd = this.ivars["@fd"].as(TInteger) + file = @fd_pool[fd.value].as(File) + TInteger.new(file.size.to_i64) + end + def init_file(kernel : TModule, fd_type : TType) file_type = TType.new("File", kernel.scope, fd_type) @@ -23,6 +30,7 @@ module Myst NativeLib.def_instance_method(file_type, :initialize, :file_init) NativeLib.def_instance_method(file_type, :close, :file_close) + NativeLib.def_instance_method(file_type, :size, :file_size) file_type end end diff --git a/stdlib/file.mt b/stdlib/file.mt index 236c452..f80d693 100644 --- a/stdlib/file.mt +++ b/stdlib/file.mt @@ -5,4 +5,6 @@ deftype File defstatic open(name : String, mode) %File{name, mode} end + + def mode; @mode; end end diff --git a/stdlib/io.mt b/stdlib/io.mt index 9cb6185..c9a3bee 100644 --- a/stdlib/io.mt +++ b/stdlib/io.mt @@ -39,14 +39,20 @@ deftype IO def gets buffer = "" last_char = "" + while last_char != "\n" buffer += last_char last_char = read(1) when last_char == "" || last_char == "\0" - return buffer + # raise/rescue is a work around for the currently-broken explicit + # returns, mentioned in https://github.com/myst-lang/myst/issues/155. + raise buffer end end + + buffer + rescue buffer buffer end end