1 /** 2 * Copyright: Enalye 3 * License: Zlib 4 * Authors: Enalye 5 */ 6 module grimoire.stdlib.range; 7 8 import std.range; 9 import grimoire.assembly, grimoire.compiler, grimoire.runtime; 10 11 package(grimoire.stdlib) void grLoadStdLibRange(GrLibrary library) { 12 library.addForeign("RangeIter", ["T"]); 13 GrType rangeIterIntType = grGetForeignType("RangeIter", [grInt]); 14 GrType rangeIterFloatType = grGetForeignType("RangeIter", [grFloat]); 15 16 library.addPrimitive(&_range_next_i, "next", [rangeIterIntType], [ 17 grBool, grInt 18 ]); 19 library.addPrimitive(&_range_i, "range", [grInt, grInt], [rangeIterIntType]); 20 library.addPrimitive(&_range_step_i, "range", [grInt, grInt, grInt], [ 21 rangeIterIntType 22 ]); 23 24 library.addPrimitive(&_range_next_f, "next", [rangeIterFloatType], [ 25 grBool, grFloat 26 ]); 27 library.addPrimitive(&_range_f, "range", [grFloat, grFloat], [ 28 rangeIterFloatType 29 ]); 30 library.addPrimitive(&_range_step_f, "range", [grFloat, grFloat, grFloat], 31 [rangeIterFloatType]); 32 } 33 34 private final class RangeIter(T) { 35 T value, end, step; 36 } 37 38 private void _range_next_i(GrCall call) { 39 RangeIter!GrInt iter = call.getForeign!(RangeIter!GrInt)(0); 40 if (!iter) { 41 call.raise("NullError"); 42 return; 43 } 44 if ((iter.step < 0 && iter.value < iter.end) || (iter.step > 0 && iter.value > iter.end)) { 45 call.setBool(false); 46 call.setInt(0); 47 return; 48 } 49 call.setBool(true); 50 call.setInt(iter.value); 51 iter.value += iter.step; 52 } 53 54 private void _range_i(GrCall call) { 55 RangeIter!GrInt iter = new RangeIter!GrInt; 56 iter.value = call.getInt(0); 57 iter.end = call.getInt(1); 58 iter.step = iter.value > iter.end ? -1 : 1; 59 call.setForeign(iter); 60 } 61 62 private void _range_step_i(GrCall call) { 63 RangeIter!GrInt iter = new RangeIter!GrInt; 64 iter.value = call.getInt(0); 65 iter.end = call.getInt(1); 66 iter.step = call.getInt(2); 67 if ((iter.value > iter.end && iter.step > 0) || (iter.value < iter.end && iter.step < 0)) { 68 iter.step = -iter.step; 69 } 70 call.setForeign(iter); 71 } 72 73 private void _range_next_f(GrCall call) { 74 RangeIter!GrFloat iter = call.getForeign!(RangeIter!GrFloat)(0); 75 if (!iter) { 76 call.raise("NullError"); 77 return; 78 } 79 if ((iter.step < 0f && iter.value < iter.end) || (iter.step > 0f && iter.value > iter.end)) { 80 call.setBool(false); 81 call.setFloat(0f); 82 return; 83 } 84 call.setBool(true); 85 call.setFloat(iter.value); 86 iter.value += iter.step; 87 } 88 89 private void _range_f(GrCall call) { 90 RangeIter!GrFloat iter = new RangeIter!GrFloat; 91 iter.value = call.getFloat(0); 92 iter.end = call.getFloat(1); 93 iter.step = iter.value > iter.end ? -1f : 1f; 94 call.setForeign(iter); 95 } 96 97 private void _range_step_f(GrCall call) { 98 RangeIter!GrFloat iter = new RangeIter!GrFloat; 99 iter.value = call.getFloat(0); 100 iter.end = call.getFloat(1); 101 iter.step = call.getFloat(2); 102 if ((iter.value > iter.end && iter.step > 0f) || (iter.value < iter.end && iter.step < 0f)) { 103 iter.step = -iter.step; 104 } 105 call.setForeign(iter); 106 }