Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 144 lines (127 sloc) 3.551 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
require "bundler/setup"
$LOAD_PATH << File.expand_path("../lib", __FILE__)
require "twostroke"
T = Twostroke::Runtime::Types
require "paint"
require "coderay"

bytecode = {}
vm = Twostroke::Runtime::VM.new bytecode
Twostroke::Runtime::Lib.setup_environment vm

def repl_inspect(obj)
  if obj.is_a? T::String
    Paint[obj.string.inspect, :green]
  elsif obj.is_a? T::Number
    Paint[obj.number.inspect, :blue, :bright]
  elsif obj.is_a? T::Boolean
    Paint[obj.boolean.inspect, :cyan, :bright]
  elsif obj.is_a? T::Null
    Paint["null", :yellow]
  elsif obj.is_a? T::Undefined
    Paint["undefined", :yellow]
  elsif obj.is_a? T::Function
    Paint[obj.name.empty? ? "[Function]" : "[Function: #{obj.name}]", :cyan]
  elsif obj.is_a? T::RegExp
    Paint[obj.regexp.inspect + (obj.global ? "g" : ""), :bright, :red]
  elsif obj.is_a? T::Array
    "[#{obj.items.reject(&:nil?).map(&method(:repl_inspect)).join(", ")}]"
  elsif obj.is_a? T::Object and obj._class == T::Object.constructor_function
    "{ #{obj.enum_for(:each_enumerable_property).map { |k| Paint[k, :magenta] + ": " + repl_inspect(obj.get(k)) }.join ", "} }"
  else
    Twostroke::Runtime::Types.to_string(obj).string
  end
end

ARGV.reject { |inc| inc =~ /^--/ }.each do |inc|
  parser = Twostroke::Parser.new(Twostroke::Lexer.new(File.read inc))
  parser.parse

  compiler = Twostroke::Compiler::TSASM.new parser.statements, "include_#{inc}_"
  compiler.compile

  compiler.bytecode.each do |k,v|
    bytecode[k] = v
  end
  
  vm.execute :"include_#{inc}_main", vm.global_scope
end

sect = 0

trap "SIGINT" do
  print "\r"
  system "stty -raw echo"
  exit!
end

loop do
  src = ""
  system "stty raw -echo"
  print Paint[">>> ", :bright]
  loop do
    c = STDIN.getc
    if c.ord == 3
      # ctrl+c
      if src.empty?
        print "\r"
        system "stty -raw echo"
        exit!
      else
        print "\r #{' ' * src.size}"
        src = ""
      end
    elsif c.ord == 127
      # backspace
      src = src[0...-1]
      print "\e[1D \e[1D"
    elsif c.ord == 24
      # ctrl+x
      src = ""
    elsif c.ord == 13
      # enter
      break
    elsif c =~ /[[:print:]]/
      src << c
    end
    print "\r"
    print Paint[">>> ", :bright]
    print CodeRay.scan(src, :javascript).encode :terminal
  end
  system "stty -raw echo"
  puts
  src << ";"

  begin
    parser = Twostroke::Parser.new(Twostroke::Lexer.new(src))
    parser.parse
  
    sect += 1
    compiler = Twostroke::Compiler::TSASM.new parser.statements, "repl_#{sect}_"
    compiler.compile
  
    compiler.bytecode.each do |k,v|
      bytecode[k] = v
    end
  
    bytecode[:"repl_#{sect}_main"][-2] = [:ret] # hacky way to make main return the last evaluated value
    obj = nil
    exception = catch(:exception) { obj = vm.execute(:"repl_#{sect}_main", vm.global_scope) || Twostroke::Runtime::Types::Undefined.new; nil }
    if exception
      obj = exception
      vm.global_scope.set_var "$EX", obj
    else
      vm.global_scope.set_var "$_", obj
    end
    str = repl_inspect obj
    if exception
      print Paint["!!!", :white, :red] + " "
    else
      print " => "
    end
    puts str
  rescue => e
    if ARGV.include? "--debug"
      puts "#{e.class.name}: #{e.message}"
      e.backtrace.each { |s| puts " #{s}" }
    else
      puts "#{e.class.name}: #{e.message}"
    end
  end
end


=begin
vm = Twostroke::Runtime::VM.new compiler.bytecode
Twostroke::Runtime::Lib.setup_environment vm.global_scope

if ARGV.include? "--pry"
require "pry"
pry binding
end

vm.execute
=end
Something went wrong with that request. Please try again.