Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Formal Front-End of Float Type Data #470

Merged
merged 8 commits into from
Nov 25, 2017
49 changes: 49 additions & 0 deletions compiler/ast/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,57 @@ import (
"strings"
)

// IntegerLiteral contains the node expression and its value
type IntegerLiteral struct {
*BaseNode
Value int
}

func (il *IntegerLiteral) expressionNode() {}

// IntegerLiteral.TokenLiteral gets the Integer type token
func (il *IntegerLiteral) TokenLiteral() string {
return il.Token.Literal
}

// IntegerLiteral.String gets the string format of the Integer type token
func (il *IntegerLiteral) String() string {
return il.Token.Literal
}

// FloatLiteral contains the node expression and its value
type FloatLiteral struct {
*BaseNode
Value float64
}

func (il *FloatLiteral) expressionNode() {}

// FloatLiteral.TokenLiteral gets the literal of the Float type token
func (il *FloatLiteral) TokenLiteral() string {
return il.Token.Literal
}

// FloatLiteral.String gets the string format of the Float type token
func (il *FloatLiteral) String() string {
return il.Token.Literal
}

// StringLiteral contains the node expression and its value
type StringLiteral struct {
*BaseNode
Value string
}

// Define the string literal which contains the node expression and its value
func (sl *StringLiteral) expressionNode() {}

// StringLiteral.TokenLiteral gets the literal of the String type token
func (sl *StringLiteral) TokenLiteral() string {
return sl.Token.Literal
}

// StringLiteral.String gets the string format of the String type token
func (sl *StringLiteral) String() string {
var out bytes.Buffer

Expand All @@ -37,15 +66,20 @@ func (sl *StringLiteral) String() string {
return out.String()
}

// ArrayExpression defines the array expression literal which contains the node expression and its value
type ArrayExpression struct {
*BaseNode
Elements []Expression
}

func (ae *ArrayExpression) expressionNode() {}

// ArrayExpression gets the literal of the Array type token
func (ae *ArrayExpression) TokenLiteral() string {
return ae.Token.Literal
}

// ArrayExpression.String gets the string format of the Array type token
func (ae *ArrayExpression) String() string {
var out bytes.Buffer

Expand Down Expand Up @@ -90,15 +124,20 @@ func (pe *PairExpression) String() string {
return fmt.Sprintf("%s: %s", pe.Key.String(), pe.Value.String())
}

// HashExpression defines the hash expression literal which contains the node expression and its value
type HashExpression struct {
*BaseNode
Data map[string]Expression
}

func (he *HashExpression) expressionNode() {}

// HashExpression.TokenLiteral gets the literal of the Hash type token
func (he *HashExpression) TokenLiteral() string {
return he.Token.Literal
}

// HashExpression.String gets the string format of the Hash type token
func (he *HashExpression) String() string {
var out bytes.Buffer
var pairs []string
Expand Down Expand Up @@ -190,15 +229,20 @@ func (ae *AssignExpression) String() string {
return out.String()
}

// BooleanExpression defines the boolean expression literal which contains the node expression and its value
type BooleanExpression struct {
*BaseNode
Value bool
}

func (b *BooleanExpression) expressionNode() {}

// BooleanExpression.TokenLiteral gets the literal of the Boolean type token
func (b *BooleanExpression) TokenLiteral() string {
return b.Token.Literal
}

// BooleanExpression.String gets the string format of the Boolean type token
func (b *BooleanExpression) String() string {
return b.Token.Literal
}
Expand Down Expand Up @@ -367,16 +411,21 @@ func (ye *YieldExpression) String() string {
return out.String()
}

// RangeExpression defines the range expression literal which contains the node expression and its start/end value
type RangeExpression struct {
*BaseNode
Start Expression
End Expression
}

func (re *RangeExpression) expressionNode() {}

// RangeExpression.TokenLiteral gets the literal of the Range type token
func (re *RangeExpression) TokenLiteral() string {
return re.Token.Literal
}

// RangeExpression.String gets the string format of the Range type token
func (re *RangeExpression) String() string {
var out bytes.Buffer

Expand Down
2 changes: 2 additions & 0 deletions compiler/bytecode/expression_generation.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ func (g *Generator) compileExpression(is *InstructionSet, exp ast.Expression, sc
is.define(GetInstanceVariable, sourceLine, exp.Value)
case *ast.IntegerLiteral:
is.define(PutObject, sourceLine, fmt.Sprint(exp.Value))
case *ast.FloatLiteral:
is.define(PutFloat, sourceLine, fmt.Sprint(exp.Value))
case *ast.StringLiteral:
is.define(PutString, sourceLine, exp.Value)
case *ast.BooleanExpression:
Expand Down
1 change: 1 addition & 0 deletions compiler/bytecode/instruction.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
SetInstanceVariable = "setinstancevariable"
PutBoolean = "putboolean"
PutString = "putstring"
PutFloat = "putfloat"
PutSelf = "putself"
PutObject = "putobject"
PutNull = "putnil"
Expand Down
20 changes: 20 additions & 0 deletions compiler/parser/data_type_parsing.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package parser

import (
"fmt"
"github.com/goby-lang/goby/compiler/ast"
"github.com/goby-lang/goby/compiler/token"
"strconv"
Expand All @@ -20,6 +21,25 @@ func (p *Parser) parseIntegerLiteral() ast.Expression {
return lit
}

func (p *Parser) parseFloatLiteral(integerPart ast.Expression) ast.Expression {
// Get the fractional part of the token
p.nextToken()

floatTok := token.Token{
Type: token.Float,
Literal: fmt.Sprintf("%s.%s", integerPart.String(), p.curToken.Literal),
Line: p.curToken.Line,
}
lit := &ast.FloatLiteral{BaseNode: &ast.BaseNode{Token: floatTok}}
value, err := strconv.ParseFloat(lit.TokenLiteral(), 64)
if err != nil {
p.error = newTypeParsingError(lit.TokenLiteral(), "float", p.curToken.Line)
return nil
}
lit.Value = float64(value)
return lit
}

func (p *Parser) parseStringLiteral() ast.Expression {
lit := &ast.StringLiteral{BaseNode: &ast.BaseNode{Token: p.curToken}}
lit.Value = p.curToken.Literal
Expand Down
12 changes: 12 additions & 0 deletions compiler/parser/expression_parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,18 @@ func (p *Parser) parseMultiVariables(left ast.Expression) ast.Expression {
return result
}

func (p *Parser) parseDotExpression(receiver ast.Expression) ast.Expression {
_, ok := receiver.(*ast.IntegerLiteral)

// When both receiver & caller are integer => Float
if ok && p.peekTokenIs(token.Int) {
Copy link
Member

@64kramsystem 64kramsystem Nov 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on this code, expresions with spaces on the sides of the dot will be parsed as floats (eg. 2 . 3).

If this is intended (other scripting languages forbid it), I think it should be documented with a test case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually currently Goby doesn't recognize white space, so it's not just float has this issue, like:

[] . length #=> 0

But this shouldn't be too hard to solve I think, already have a rough idea. But that won't be included in this PR.

return p.parseFloatLiteral(receiver)
}

// Normal call method expression with receiver
return p.parseCallExpressionWithReceiver(receiver)
}

func (p *Parser) expandAssignmentValue(value ast.Expression) ast.Expression {
switch p.curToken.Type {
case token.Assign:
Expand Down
2 changes: 1 addition & 1 deletion compiler/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func New(l *lexer.Lexer) *Parser {
p.registerInfix(token.ResolutionOperator, p.parseInfixExpression)
p.registerInfix(token.Assign, p.parseAssignExpression)
p.registerInfix(token.Range, p.parseRangeExpression)
p.registerInfix(token.Dot, p.parseCallExpressionWithReceiver)
p.registerInfix(token.Dot, p.parseDotExpression)
p.registerInfix(token.LParen, p.parseCallExpressionWithoutReceiver)
p.registerInfix(token.LBracket, p.parseIndexExpression)
p.registerInfix(token.Colon, p.parsePairExpression)
Expand Down
1 change: 1 addition & 0 deletions compiler/token/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
Ident = "IDENT"
InstanceVariable = "INSTANCE_VAR"
Int = "INT"
Float = "FLOAT"
String = "STRING"
Comment = "COMMENT"

Expand Down
4 changes: 2 additions & 2 deletions vm/float.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package vm

import (
"math"
"strconv"

"github.com/goby-lang/goby/vm/classes"
"github.com/goby-lang/goby/vm/errors"
"strconv"
)

// FloatObject represents an inexact real number using the native architecture's double-precision floating point
Expand Down Expand Up @@ -438,7 +438,7 @@ func (f *FloatObject) numericComparison(t *thread, rightObject Object, operation
// toString returns the object's value as the string format, in non
// exponential format (straight number, without exponent `E<exp>`).
func (f *FloatObject) toString() string {
return strconv.FormatFloat(f.value, 'f', -1, 64)
return strconv.FormatFloat(f.value, 'f', -1, 64) // fmt.Sprintf("%f", f.value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment intended?

}

// toJSON just delegates to toString
Expand Down
Loading