Skip to content

Commit

Permalink
Merge 2c8b85f into 656eb27
Browse files Browse the repository at this point in the history
  • Loading branch information
project-eutopia committed Nov 22, 2018
2 parents 656eb27 + 2c8b85f commit c47ea64
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 13 deletions.
1 change: 1 addition & 0 deletions lib/keisan.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
require "keisan/ast/null"
require "keisan/ast/boolean"
require "keisan/ast/date"
require "keisan/ast/time"

require "keisan/ast/block"
require "keisan/ast/parent"
Expand Down
12 changes: 12 additions & 0 deletions lib/keisan/ast.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "date"
require "time"

module Keisan
module AST
Expand Down Expand Up @@ -88,6 +89,16 @@ def value(context = nil)
end
end

module KeisanTime
def to_node
Keisan::AST::Time.new(self)
end

def value(context = nil)
self
end
end

class Numeric; prepend KeisanNumeric; end
class String; prepend KeisanString; end
class TrueClass; prepend KeisanTrueClass; end
Expand All @@ -96,3 +107,4 @@ class NilClass; prepend KeisanNilClass; end
class Array; prepend KeisanArray; end
class Hash; prepend KeisanHash; end
class Date; prepend KeisanDate; end
class Time; prepend KeisanTime; end
8 changes: 4 additions & 4 deletions lib/keisan/ast/date.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
module Keisan
module AST
class Date < ConstantLiteral
attr_reader :content
attr_reader :date

def initialize(content)
@content = content
def initialize(date)
@date = date
end

def value(context = nil)
content
date
end

def +(other)
Expand Down
2 changes: 2 additions & 0 deletions lib/keisan/ast/number.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ def +(other)
Number.new(value + other.value)
when Date
Date.new(other.value + value)
when Time
Time.new(other.value + value)
else
super
end
Expand Down
12 changes: 9 additions & 3 deletions lib/keisan/ast/plus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def value(context = nil)
elsif children_values.all? {|child| child.is_a?(::Array)}
children_values.inject([], &:+)
elsif children_values.one? {|child| child.is_a?(::Date)}
date = children_values.select {|child| child.is_a?(::Date)}.first
others = children_values.select {|child| !child.is_a?(::Date)}
date + others.inject(0, &:+)
date_time_plus(children_values, ::Date)
elsif children_values.one? {|child| child.is_a?(::Time)}
date_time_plus(children_values, ::Time)
else
children_values.inject(0, &:+)
end.to_node.value(context)
Expand Down Expand Up @@ -81,6 +81,12 @@ def differentiate(variable, context = nil)

private

def date_time_plus(elements, klass)
date_time = elements.select {|child| child.is_a?(klass)}.first
others = elements.select {|child| !child.is_a?(klass)}
date_time + others.inject(0, &:+)
end

def convert_minus_to_plus!
@parsing_operators.each.with_index do |parsing_operator, index|
if parsing_operator.is_a?(Parsing::Minus)
Expand Down
59 changes: 59 additions & 0 deletions lib/keisan/ast/time.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module Keisan
module AST
class Time < ConstantLiteral
attr_reader :time

def initialize(time)
@time = time
end

def value(context = nil)
time
end

def +(other)
other = other.to_node
case other
when Number
self.class.new(value + other.value)
else
super
end
end

def to_s
value.strftime("%Y-%m-%d %H:%M:%S")
end

def >(other)
other = other.to_node
other.is_a?(AST::Time) ? Boolean.new(value > other.value) : super
end

def >=(other)
other = other.to_node
other.is_a?(AST::Time) ? Boolean.new(value >= other.value) : super
end

def <(other)
other = other.to_node
other.is_a?(AST::Time) ? Boolean.new(value < other.value) : super
end

def <=(other)
other = other.to_node
other.is_a?(AST::Time) ? Boolean.new(value <= other.value) : super
end

def equal(other)
other = other.to_node
other.is_a?(AST::Time) ? Boolean.new(value == other.value) : super
end

def not_equal(other)
other = other.to_node
other.is_a?(AST::Time) ? Boolean.new(value != other.value) : super
end
end
end
end
2 changes: 1 addition & 1 deletion lib/keisan/functions/date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Keisan
module Functions
class Date < ProcFunction
def initialize
@name = "sample"
@name = "date"
@arity = ::Range.new(1, 3)
end

Expand Down
11 changes: 11 additions & 0 deletions lib/keisan/functions/default_registry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
require_relative "real"
require_relative "imag"
require_relative "date"
require_relative "time"

module Keisan
module Functions
Expand Down Expand Up @@ -134,6 +135,16 @@ def self.register_date_time_methods!(registry)
registry.register!(:weekday, Proc.new {|d| d.wday }, force: true)
registry.register!(:month, Proc.new {|d| d.month }, force: true)
registry.register!(:year, Proc.new {|d| d.year }, force: true)

registry.register!(:time, Keisan::Functions::Time.new, force: true)
registry.register!(:now, Proc.new { ::Time.now }, force: true)
registry.register!(:hour, Proc.new {|t| t.hour }, force: true)
registry.register!(:minute, Proc.new {|t| t.min }, force: true)
registry.register!(:second, Proc.new {|t| t.sec }, force: true)
registry.register!(:strftime, Proc.new {|*args| args.first.strftime(*args[1..-1]) }, force: true)

registry.register!(:to_time, Proc.new {|d| d.to_time }, force: true)
registry.register!(:to_date, Proc.new {|t| t.to_date }, force: true)
end
end
end
Expand Down
20 changes: 20 additions & 0 deletions lib/keisan/functions/time.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require "time"

module Keisan
module Functions
class Time < ProcFunction
def initialize
@name = "time"
@arity = ::Range.new(1, 7)
end

def call(context, *args)
if args.count == 1 && args.first.is_a?(::String)
AST::Time.new(::Time.parse(args.first))
else
AST::Time.new(::Time.new(*args))
end
end
end
end
end
18 changes: 13 additions & 5 deletions spec/keisan/ast/date_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
ast = Keisan::AST.parse("date(2000) + date(2000)")
expect(ast.evaluate).to be_a(Keisan::AST::Plus)
expect{ast.evaluate.value}.to raise_error(TypeError)
# expect(ast.evaluate.value).to eq false
end

it "works in arrays" do
Expand All @@ -65,36 +64,45 @@
end

describe "weekday" do
it "weekday number" do
it "returns the weekday number" do
ast = Keisan::AST.parse("date(2018, 11, 20).weekday()")
expect(ast.evaluate).to be_a(Keisan::AST::Number)
expect(ast.evaluate.value).to eq 2
end
end

describe "day" do
it "day number in month" do
it "returns the day number in month" do
ast = Keisan::AST.parse("date(2018, 11, 20).day()")
expect(ast.evaluate).to be_a(Keisan::AST::Number)
expect(ast.evaluate.value).to eq 20
end
end

describe "month" do
it "month number" do
it "returns the month number" do
ast = Keisan::AST.parse("date(2018, 11, 20).month()")
expect(ast.evaluate).to be_a(Keisan::AST::Number)
expect(ast.evaluate.value).to eq 11
end
end

describe "year" do
it "year number" do
it "returns the year number" do
ast = Keisan::AST.parse("date(2018, 11, 20).year()")
expect(ast.evaluate).to be_a(Keisan::AST::Number)
expect(ast.evaluate.value).to eq 2018
end
end

describe "#to_time" do
it "converts date to time" do
calculator = Keisan::Calculator.new
time = calculator.ast("date(2018, 11, 20).to_time").evaluate
expect(time).to be_a(Keisan::AST::Time)
expect(time.to_s).to eq "2018-11-20 00:00:00"
end
end
end

describe "#to_s" do
Expand Down

0 comments on commit c47ea64

Please sign in to comment.