Module: Apricot

Defined in:
lib/apricot/misc.rb,
lib/apricot/seq.rb,
lib/apricot/boot.rb,
lib/apricot/cons.rb,
lib/apricot/list.rb,
lib/apricot/repl.rb,
lib/apricot/errors.rb,
lib/apricot/reader.rb,
lib/apricot/scopes.rb,
lib/apricot/version.rb,
lib/apricot/compiler.rb,
lib/apricot/generator.rb,
lib/apricot/namespace.rb,
lib/apricot/variables.rb,
lib/apricot/identifier.rb,
lib/apricot/code_loader.rb,
lib/apricot/macroexpand.rb,
lib/apricot/special_forms.rb,
lib/apricot/special_forms/do.rb,
lib/apricot/special_forms/fn.rb,
lib/apricot/special_forms/if.rb,
lib/apricot/special_forms/def.rb,
lib/apricot/special_forms/dot.rb,
lib/apricot/special_forms/let.rb,
lib/apricot/special_forms/try.rb,
lib/apricot/special_forms/loop.rb,
lib/apricot/special_forms/quote.rb,
lib/apricot/special_forms/recur.rb

Overview

This file contains some things that are used in a bunch of places and don’t fit anywhere in particular.

Defined Under Namespace

Modules: CodeLoader, Compiler, Seq, StorageScope Classes: CompileError, Cons, FnScope, Generator, Identifier, LetScope, List, LocalReference, Namespace, OverloadScope, QualifiedReference, REPL, Reader, Scope, SpecialForm, SyntaxError, TopLevelScope

Constant Summary collapse

LIB_PATH =
File.expand_path("../../../kernel", __FILE__)
Core =
Namespace.new
VERSION =
'0.0.2'

Class Method Summary collapse

Class Method Details

.compile_error(file, line, msg) ⇒ Object

Raises:



35
36
37
# File 'lib/apricot/errors.rb', line 35

def self.compile_error(file, line, msg)
  raise CompileError.new(file, line, msg)
end

.current_namespaceObject



68
69
70
# File 'lib/apricot/namespace.rb', line 68

def current_namespace
  Core.get_var(:"*ns*")
end

.current_namespace=(ns) ⇒ Object



72
73
74
# File 'lib/apricot/namespace.rb', line 72

def current_namespace=(ns)
  Core.set_var(:"*ns*", ns)
end

.gensym(prefix = 'g') ⇒ Object



8
9
10
11
# File 'lib/apricot/misc.rb', line 8

def self.gensym(prefix = 'g')
  @gensym += 1
  Identifier.intern("#{prefix}__#{@gensym}")
end

.let(g, args, type) ⇒ Object

Code shared between let and loop. type is :let or :loop



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
# File 'lib/apricot/special_forms.rb', line 24

def self.let(g, args, type)
  g.compile_error "Too few arguments to #{type}" if args.count < 1
  g.compile_error "First argument to #{type} must be an array literal" unless args.first.is_a? Array

  bindings, body = args.first, args.rest

  g.compile_error "Bindings array for #{type} must contain an even number of forms" if bindings.length.odd?

  scope = LetScope.new(g.scope)
  g.scopes << scope

  bindings.each_slice(2) do |id, value|
    g.compile_error "Binding targets in #{type} must be identifiers" unless id.is_a? Identifier

    Compiler.bytecode(g, value)
    g.set_local scope.new_local(id)
    g.pop
  end

  if type == :loop
    scope.loop_label = g.new_label
    scope.loop_label.set!
  end

  SpecialForm[:do].bytecode(g, body)

  g.scopes.pop
end

.load(file) ⇒ Object



2
3
4
# File 'lib/apricot/code_loader.rb', line 2

def self.load(file)
  CodeLoader.load(file)
end

.macroexpand(form) ⇒ Object



2
3
4
5
6
7
8
9
10
11
# File 'lib/apricot/macroexpand.rb', line 2

def self.macroexpand(form)
  ex = macroexpand_1(form)

  until ex.equal?(form)
    form = ex
    ex = macroexpand_1(form)
  end

  ex
end

.macroexpand_1(form) ⇒ Object



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
# File 'lib/apricot/macroexpand.rb', line 13

def self.macroexpand_1(form)
  return form unless form.is_a? Seq

  callee = form.first
  return form unless callee.is_a?(Identifier) && !callee.constant?

  name = callee.name
  name_s = name.to_s
  args = form.rest

  # Handle the (.method receiver args*) send expression form
  if name.length > 1 && name != :'..' && name_s.start_with?('.')
    raise ArgumentError, "Too few arguments to send expression, expecting (.method receiver ...)" if args.empty?

    dot = Identifier.intern(:'.')
    method = Identifier.intern(name_s[1..-1])
    return List[dot, args.first, method, *args.rest]
  end

  # Handle the (Class. args*) shorthand new form
  if name.length > 1 && name != :'..' && name_s.end_with?('.')
    dot = Identifier.intern(:'.')
    klass = Identifier.intern(name_s[0..-2])
    new = Identifier.intern(:new)
    return List[dot, klass, new, *args]
  end

  # Handle defined macros
  if callee.qualifier.is_a?(Namespace) && callee.qualifier.vars.include?(callee.unqualified_name)
    potential_macro = callee.qualifier.get_var(callee.unqualified_name)
    meta = potential_macro.apricot_meta

    if meta && meta[:macro]
      return potential_macro.call(*args)
    end
  end

  # Default case
  form
end

.require(file) ⇒ Object



6
7
8
# File 'lib/apricot/code_loader.rb', line 6

def self.require(file)
  CodeLoader.require(file)
end