Repository: vyperlang/vyper

Issue:
Assignment allowed to invalid variables in contract body
* viper Version: 0.0.2
* pyethereum Version: 2.1.0
* OS: linux
* Python Version (python --version): 3.6

### What's your issue about?

It appears that some programs parse which perhaps should not, including assigning to a global-style declaration in function bodies.  These programs then behave unexpectedly.  Below is a minimal example:

```
from ethereum.tools import tester as t
from ethereum.slogging import configure_logging

#configure_logging(':trace')
s = t.Chain()
from viper import com
piler

code = """
def foo() -> num:
    q:num = 1
    return q

def foo2() -> num:
    q = 1
    return q
"""

t.languages['viper'] = compiler.Compiler() 

c = s.contract(code, language='viper')

print(c.foo())  # Should not parse? returns 0
print(c.foo2()) # Should return 1; returns 1
```

**This bug was discovered by Yi Zhang of the [KEVM project](https://github.com/kframework/evm-semantics). (@yzhang90)**

### How can it be fixed?

Make parsing consistent with what is specified in the old README.

Specifically, the offending statement can parse under these top-level rules:
```
 <varname> = <type>
        OR <var> = <expr>
```

with "q:num" being neither a valid varname or var (assuming varnames cannot contain colons, which would be sane).

Parsing should therefore likely fail in this case.

#### Cute Animal Picture

```
             ,,,,,,,,
           ,|||````||||
     ,,,,|||||       ||,
  ,||||```````       `||
,|||`                 |||,
||`     ....,          `|||
||     ::::::::          |||,
||     :::::::'     ||    ``|||,
||,     :::::'               `|||
`||,                           |||
 `|||,       ||          ||    ,||
   `||                        |||`
    ||                   ,,,||||
    ||              ,||||||```
   ,||         ,,|||||`
  ,||`   ||   |||`
 |||`         ||
,||           ||
||`           ||
|||,         |||
 `|||,,    ,|||
   ``||||||||`
```


Discussion:
@pdaian Thanks for making an issue, I'll look into it right away!
Interestingly enough the following works as tested, as spotted by @yzhang90

```
def foo() -> num:
    p:{x:num, y:num}
    p.x = 2
    p.y = 3
    return p.y
```
@pdaian @yzhang90 good catch ! :fish: 

Resolving patch:
diff --git a/viper/parser/parser.py b/viper/parser/parser.py
--- a/viper/parser/parser.py
+++ b/viper/parser/parser.py
@@ -171,7 +171,9 @@ def add_contract(code):
 
 
 def add_globals_and_events(_defs, _events, _getters, _globals, item):
-    if isinstance(item.annotation, ast.Call) and item.annotation.func.id == "__log__":
+    if item.value is not None:
+        raise StructureException('May not assign value whilst defining type', item)
+    elif isinstance(item.annotation, ast.Call) and item.annotation.func.id == "__log__":
         if _globals or len(_defs):
             raise StructureException("Events must all come before global declarations and function definitions", item)
         _events.append(item)
diff --git a/viper/parser/stmt.py b/viper/parser/stmt.py
--- a/viper/parser/stmt.py
+++ b/viper/parser/stmt.py
@@ -69,6 +69,8 @@ def parse_pass(self):
         return LLLnode.from_list('pass', typ=None, pos=getpos(self.stmt))
 
     def ann_assign(self):
+        if self.stmt.value is not None:
+            raise StructureException('May not assign value whilst defining type', self.stmt)
         typ = parse_type(self.stmt.annotation, location='memory')
         varname = self.stmt.target.id
         pos = self.context.new_variable(varname, typ)


Test patch:
diff --git a/tests/parser/exceptions/test_structure_exception.py b/tests/parser/exceptions/test_structure_exception.py
--- a/tests/parser/exceptions/test_structure_exception.py
+++ b/tests/parser/exceptions/test_structure_exception.py
@@ -131,6 +131,16 @@ def foo():
     """
 def foo():
     x = y = 3
+    """,
+    """
+def foo() -> num:
+    q:num = 111
+    return q
+    """,
+    """
+q:num = 111
+def foo() -> num:
+    return self.q
     """
 ]