From 17212f816ce630cdb9627af4aee4f07a61abb994 Mon Sep 17 00:00:00 2001
From: Alexander Medvednikov <alexander@medvednikov.com>
Date: Tue, 11 Feb 2020 13:21:41 +0100
Subject: [PATCH] v2: high order functions

---
 vlib/builtin/array.v       |  2 +-
 vlib/v/parser/fn.v         |  4 ++--
 vlib/v/parser/parse_type.v |  9 +++++++--
 vlib/v/parser/parser.v     | 10 +++++++---
 vlib/v/token/token.v       |  4 ++++
 5 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v
index 1d7c54ec37..8ac2d8fff8 100644
--- a/vlib/builtin/array.v
+++ b/vlib/builtin/array.v
@@ -449,7 +449,6 @@ pub fn (a []char) index(v char) int {
 	return -1
 }
 
-/*
 // []int.reduce executes a given reducer function on each element of the array,
 // resulting in a single output value.
 pub fn (a []int) reduce(iter fn(accum, curr int)int, accum_start int) int {
@@ -461,6 +460,7 @@ pub fn (a []int) reduce(iter fn(accum, curr int)int, accum_start int) int {
 	return _accum
 }
 
+/*
 // array_eq<T> checks if two arrays contain all the same elements in the same order.
 // []int == []int (also for: i64, f32, f64, byte, string)
 fn array_eq<T>(a1, a2 []T) bool {
diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v
index e03daae1ec..b718851767 100644
--- a/vlib/v/parser/fn.v
+++ b/vlib/v/parser/fn.v
@@ -92,7 +92,6 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
 		p.check(.gt)
 	}
 	// println('fn decl $name')
-	p.check(.lpar)
 	// Args
 	mut args := []table.Var
 	ast_args,is_variadic := p.fn_args()
@@ -122,7 +121,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
 				*/
 	// Return type
 	mut typ := table.void_type
-	if p.tok.kind in [.name, .lpar, .amp, .lsbr, .question] {
+	if p.tok.kind.is_start_of_type() {
 		typ = p.parse_type()
 	}
 	p.return_type = typ
@@ -165,6 +164,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
 }
 
 fn (p mut Parser) fn_args() ([]ast.Arg,bool) {
+	p.check(.lpar)
 	mut args := []ast.Arg
 	mut is_variadic := false
 	// `int, int, string` (no names, just types)
diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v
index 51b2033192..55ffee03d6 100644
--- a/vlib/v/parser/parse_type.v
+++ b/vlib/v/parser/parse_type.v
@@ -67,8 +67,13 @@ pub fn (p mut Parser) parse_multi_return_type() table.Type {
 }
 
 pub fn (p mut Parser) parse_fn_type() table.Type {
-	// p.check(.key_fn)
-	p.fn_decl()
+	p.warn('parrse fn')
+	p.check(.key_fn)
+	// p.fn_decl()
+	p.fn_args()
+	if p.tok.kind.is_start_of_type() {
+		p.parse_type()
+	}
 	return table.int_type
 }
 
diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v
index 07e463de24..13d7c9819a 100644
--- a/vlib/v/parser/parser.v
+++ b/vlib/v/parser/parser.v
@@ -635,7 +635,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
 			node,typ = p.dot_expr(node, typ)
 		}
 		else if p.tok.kind == .lsbr {
-			//node = p.index_expr(node) // , typ)
+			// node = p.index_expr(node) // , typ)
 			ie_node,ie_typ := p.index_expr(node, typ)
 			node = ie_node
 			typ = ie_typ
@@ -869,7 +869,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
 	}
 	// `for i in vals`, `for i in start .. end`
 	else if p.peek_tok.kind in [.key_in, .comma] {
-	var_name := p.check_name()
+		var_name := p.check_name()
 		if p.tok.kind == .comma {
 			p.check(.comma)
 			val_name := p.check_name()
@@ -900,7 +900,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
 					// elem_type_sym := p.table.get_type_symbol(elem_type)
 					// p.error('cannot loop over type: $elem_type_sym.name')
 				}
-			}
+	}
 		}
 		// 0 .. 10
 		// start := p.tok.lit.int()
@@ -1104,6 +1104,10 @@ fn (p mut Parser) module_decl() ast.Module {
 
 fn (p mut Parser) parse_import() ast.Import {
 	mod_name := p.check_name()
+	if p.tok.kind == .dot {
+		p.next()
+		p.check_name()
+	}
 	mut mod_alias := mod_name
 	if p.tok.kind == .key_as {
 		p.check(.key_as)
diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v
index baa495b676..40b4bf2e92 100644
--- a/vlib/v/token/token.v
+++ b/vlib/v/token/token.v
@@ -463,6 +463,10 @@ pub fn (tok Kind) is_relational() bool {
 	.lt, .le, .gt, .ge, .eq, .ne]
 }
 
+pub fn (k Kind) is_start_of_type() bool {
+	return k in [.name, .lpar, .amp, .lsbr, .question]
+}
+
 pub fn (kind Kind) is_infix() bool {
 	return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in,
 	//