summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/lineinfos.nim5
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/semtypes.nim2
3 files changed, 5 insertions, 4 deletions
diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim
index 9c10105b1..eea55defc 100644
--- a/compiler/lineinfos.nim
+++ b/compiler/lineinfos.nim
@@ -39,7 +39,7 @@ type
     warnEachIdentIsTuple,
     warnUnsafeSetLen,
     warnUnsafeDefault,
-    warnProveInit, warnProveField, warnProveIndex,
+    warnProveInit, warnProveField, warnProveIndex, warnUnreachableElse,
     warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2,
     warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
     warnInconsistentSpacing, warnCaseTransition, warnCycleCreated, warnUser,
@@ -96,6 +96,7 @@ const
     warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
     warnProveField: "cannot prove that field '$1' is accessible",
     warnProveIndex: "cannot prove index '$1' is valid",
+    warnUnreachableElse: "unreachable else, all cases are already covered",
     warnStaticIndexCheck: "$1",
     warnGcUnsafe: "not GC-safe: '$1'",
     warnGcUnsafe2: "$1",
@@ -153,7 +154,7 @@ const
     "UnsafeCode", "UnusedImport", "InheritFromException",
     "EachIdentIsTuple",
     "UnsafeSetLen", "UnsafeDefault",
-    "ProveInit", "ProveField", "ProveIndex",
+    "ProveInit", "ProveField", "ProveIndex", "UnreachableElse",
     "IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit",
     "GcMem", "Destructor", "LockLevel", "ResultShadowed",
     "Spacing", "CaseTransition", "CycleCreated", "User"]
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 6ebe5723e..22055a33d 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -998,7 +998,7 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
       x[0] = semExprBranchScope(c, x[0])
       typ = commonType(typ, x[0])
       if (chckCovered and covered == toCover(c, n[0].typ)) or hasElse:
-        localError(c.config, x.info, "invalid else, all cases are already covered")
+        message(c.config, x.info, warnUnreachableElse)
       hasElse = true
       chckCovered = false
     else:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index e6cbe56e8..a069fba60 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -695,7 +695,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
     of nkElse:
       checkSonsLen(b, 1, c.config)
       if chckCovered and covered == toCover(c, a[0].typ):
-        localError(c.config, b.info, "invalid else, all cases are already covered")
+        message(c.config, b.info, warnUnreachableElse)
       chckCovered = false
     else: illFormedAst(n, c.config)
     delSon(b, b.len - 1)
2742f2fc4159b6e9a99e85d183f'>^
f40137f1 ^
263e6b2a ^
385d3080 ^

1211a3ab ^
385d3080 ^

1211a3ab ^
385d3080 ^



b24eb476 ^
385d3080 ^

5937f1af ^
3473c63a ^
af023b32 ^
0f2781f8 ^
3473c63a ^




385d3080 ^

b24eb476 ^
385d3080 ^

1b76245c ^
263e6b2a ^
385d3080 ^

dfc6e268 ^



1ead3562 ^
897ae8c1 ^
192d59d3 ^

dfc6e268 ^
5f98a10c ^

dfc6e268 ^





385d3080 ^

af023b32 ^

385d3080 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82





                                                                             



                                                                            

                        
          
                                                             

                              
                                                             

                              
                               

                                       

                               
 
                                                                       
                               
                                                                                            
                               

                                                                      
                                             

                             
                                             



                                                                
                 

                                   
                                                 
                               
                                    
                                                                                                                                                                    




                                                                                              

                                                                          
                                           

                                       
                                                        
                                                              

   



                                                           
          
                                             

                               
 

                                                         





                                                     

                                  

                                              
 
//: So far we have local variables, and we can nest local variables of short
//: lifetimes inside longer ones. Now let's support 'global' variables that
//: last for the life of a routine. If we create multiple routines they won't
//: have access to each other's globals.
//:
//: This feature is still experimental and half-baked. You can't name global
//: variables, and they don't get checked for types (the only known hole in
//: the type system, can cause memory corruption). We might fix these issues
//: if we ever use globals. Or we might just drop the feature entirely.
//: [tag: todo]

:(scenario global_space)
def main [
  # pretend address:array:location; in practice we'll use new
  10:num <- copy 0  # refcount
  11:num <- copy 5  # length
  # pretend address:array:location; in practice we'll use new
  20:num <- copy 0  # refcount
  21:num <- copy 5  # length
  # actual start of this recipe
  global-space:space <- copy 20/unsafe
  default-space:space <- copy 10/unsafe
  1:num <- copy 23
  1:num/space:global <- copy 24
]
# store to default space: 10 + (skip refcount and length) 2 + (index) 1
+mem: storing 23 in location 13
# store to chained space: (contents of location 12) 20 + (refcount and length) 2 + (index) 1
+mem: storing 24 in location 23

//: to support it, create another special variable called global space
:(before "End is_disqualified Special-cases")
if (x.name == "global-space")
  x.initialized = true;
:(before "End is_special_name Special-cases")
if (s == "global-space") return true;

//: writes to this variable go to a field in the current routine
:(before "End routine Fields")
int global_space;
:(before "End routine Constructor")
global_space = 0;
:(after "Begin Preprocess write_memory(x, data)")
if (x.name == "global-space") {
  if (!scalar(data) || !is_space(x))
    raise << maybe(current_recipe_name()) << "'global-space' should be of type address:array:location, but tried to write '" << to_string(x.type) << "'\n" << end();
  if (Current_routine->global_space)
    raise << "routine already has a global-space; you can't over-write your globals" << end();
  Current_routine->global_space = data.at(0);
  return;
}

//: now marking variables as /space:global looks them up inside this field
:(after "int space_base(const reagent& x)")
  if (is_global(x)) {
    if (!Current_routine->global_space)
      raise << "routine has no global space\n" << end();
    return Current_routine->global_space + /*skip refcount*/1;
  }

//: for now let's not bother giving global variables names.
//: don't want to make them too comfortable to use.

:(scenario global_space_with_names)
def main [
  global-space:space <- new location:type, 10
  x:num <- copy 23
  1:num/space:global <- copy 24
]
# don't complain about mixing numeric addresses and names
$error: 0

:(after "bool is_numeric_location(const reagent& x)")
  if (is_global(x)) return false;

//: helpers

:(code)
bool is_global(const reagent& x) {
  string_tree* s = property(x, "space");
  return s && s->atom && s->value == "global";
}