Skip to content

Commit

Permalink
Initial Release
Browse files Browse the repository at this point in the history
  • Loading branch information
pandeykartikey committed Jun 29, 2020
1 parent 24cd105 commit 1bd406c
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 16 deletions.
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Goto is a dynamically typed programming language written to support all the scri
- Grouped Expressions
- Functions
- Scopes
- Comments
- Error Handling
- Built in Functions: `append`, `print`, `len`

Expand Down Expand Up @@ -66,7 +67,12 @@ To execute a goto-script, pass the name to the interpreter:

$ goto sample.to

To drop into goto-repl, type `goto`.
Scripts can be made executable by adding a suitable shebang line:

#!/usr/bin/env goto


To drop into goto-repl, type `goto`. To exit from repl, just type `exit` or `Ctrl + D`.

## 5. Syntax

Expand All @@ -92,8 +98,8 @@ The datatypes of all the variables need not be the same.
Goto supports hiding of global variable in block constructs

var a = 4;
if true { var a = 5; print(a);} //prints 5
print(a); //prints 4
if true { var a = 5; print(a);} # prints 5
print(a); # prints 4


### 5.2 Arithmetic operations
Expand All @@ -111,19 +117,19 @@ List is a data structure that organizes items by linear sequence. It can hold mu
Lists are 0-indexed. Elements can be accessed using []. Similar indexing exists for strings.

var a = [1, true, "array"];
a[1] // returns true
a[2][3] // returns "a"
a[1] # returns true
a[2][3] # returns "a"

### 5.4 Builtin functions
Goto currently supports 3 built-in functions:
1. `len`: Returns the length of string or a list.

len("goto") //returns 4
len("goto") # returns 4

2. `append`: appends a token at the end of an array

var a = [1, 2];
append(a, 3) // a becomes [1, 2, 3]
append(a, 3) # a becomes [1, 2, 3]

3. `print`: prints the content of parameters to STDOUT. It can take multiple arguments.

Expand All @@ -143,7 +149,7 @@ Goto defines function using `func` followed by an identifier and a parameter lis
You can define local functions inside a block statement with limited scope.

func addTwo(x) {
func addOne(x) { // addOne() is limited to addTwo()'s scope
func addOne(x) { # addOne() is limited to addTwo()'s scope
return x + 1;
}
x = addOne(x);
Expand All @@ -163,7 +169,7 @@ Goto supports if-else-if statements.
} else {
c = 30;
}
print(c); //returns 20
print(c); # returns 20

### 5.7 For-loop statements
Goto has supports for-loop statements.
Expand All @@ -189,6 +195,10 @@ There are three control flow statements in goto:

3. `return`: It is used to terminate a function. It may also be used to return values from functions.

### 5.9 Comments
Single Line comments are supported by goto.

# This is a comment

## 6. Contributing
If you spot anything that seems wrong, please do [report an issue](https://github.com/pandeykartikey/goto/issues).
Expand Down
11 changes: 11 additions & 0 deletions lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ func (l *Lexer) skipWhitespace() {
}
}

func (l *Lexer) skipComments() {
if l.ch == '#' {
for l.ch != '\n' && l.ch != 0 {
l.readChar()
}
}
}

func (l *Lexer) readSequence(f func(byte) bool) string {
position := l.position

Expand Down Expand Up @@ -79,6 +87,9 @@ func (l *Lexer) NextToken() token.Token {
tok.Literal = l.readSequence(isDigit)
tok.Type = token.INT
return tok
} else if l.ch == '#' {
l.skipComments()
return l.NextToken()
} else {
tok = newToken(token.ILLEGAL, l.ch)
}
Expand Down
3 changes: 1 addition & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ func main() {
fmt.Println(result.Inspect())
}
} else {
fmt.Printf("GoTo 0.1.0\n")

fmt.Println("Goto 0.1.0")
repl.Start()
}
}
8 changes: 7 additions & 1 deletion parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ func (p *Parser) parseExpressionList() *ast.ExpressionList {
return args
}

if p.currTokenIs(token.EOF) {
p.errors = append(p.errors, "End Of File encountered while parsing")
}

return nil
}

Expand Down Expand Up @@ -337,7 +341,7 @@ func (p *Parser) parseAssignment(isExpression bool) *ast.Assignment {

assign.ValueList = p.parseExpressionList()

if len(assign.ValueList.Expressions) != len(assign.NameList.Identifiers) {
if assign.ValueList == nil || assign.NameList == nil || len(assign.ValueList.Expressions) != len(assign.NameList.Identifiers) {
p.errors = append(p.errors, "Mismatch in number of values on both side of =")
}

Expand Down Expand Up @@ -582,6 +586,8 @@ func (p *Parser) parseStatement() ast.Statement {
return nil
case token.SEMI:
return nil
case token.EOF:
return nil
case token.IDENT:
if p.peekTokenIs(token.COMMA) || p.peekTokenIs(token.ASSIGN) {
return p.parseAssignment(false)
Expand Down
15 changes: 13 additions & 2 deletions repl/repl.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func Start() {

term := liner.NewLiner()
defer term.Close()
term.SetCtrlCAborts(true)

env := object.NewEnvironment()
code := ""
Expand All @@ -30,11 +31,21 @@ func Start() {
line, err := term.Prompt(prompt)

if err != nil {
fmt.Println("Aborted")
if err == liner.ErrPromptAborted {
code = ""
prompt = PS1
continue
} else {
fmt.Println("Aborted")
}
break
}

if line == "exit" {
break
}

code += line
code += "\n" + line

l := lexer.New(code)
p := parser.New(l)
Expand Down
6 changes: 4 additions & 2 deletions sample.to
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
func identity(x) {
#!/usr/bin/env goto

func identity(x) { # An identity function
return x;
}

print(identity(4));
print(identity(4));

0 comments on commit 1bd406c

Please sign in to comment.