Wiki

Ticket #71: for-expr-numeric.patch

File for-expr-numeric.patch, 8.5 KB (added by hopscc, 16 years ago)
  • Source/Expr.cobra

     
    865865    var _what as Expr 
    866866    var _whereExpr as Expr? 
    867867    var _getExpr as Expr 
     868    var _start as Expr? 
     869    var _stop as Expr? 
     870    var _step as Expr? 
    868871 
    869     def init(token as IToken, nameExpr as NameExpr, what as Expr, whereExpr as Expr?, getExpr as Expr) 
     872    def init(token as IToken, nameExpr as NameExpr, what as Expr, stopExpr as Expr?,  
     873                stepExpr as Expr?, whereExpr as Expr?, getExpr as Expr) 
    870874        base.init(token) 
    871875        _nameExpr = nameExpr 
    872876        _what = what 
     877        _stop = stopExpr 
     878        _step = stepExpr 
    873879        _whereExpr = whereExpr 
    874880        _getExpr = getExpr 
    875881 
     
    880886        .addField('what', _what) 
    881887        .addField('whereExpr', _whereExpr) 
    882888        .addField('getExpr', _getExpr) 
     889        .addField('start', _start) 
     890        .addField('stop', _stop) 
     891        .addField('step', _step) 
    883892 
    884893    get willChangeVar as bool is override 
    885894        # TODO: ack. kind of weird. if the variable is a new one and its not read afterwards (without first being set) then no side effects. 
     
    892901        base._bindImp 
    893902        _what.bindImp  # bind first because it may be needed for type inference 
    894903        whatType = _what.type to ! 
    895         if not whatType.isDescendantOf(.compiler.enumerableType) and not whatType.isSequenceLike  # TODO: can probably drop .isSequenceLike 
     904        if whatType inherits AnyIntType 
     905            if _stop 
     906                _start = _what 
     907                _stop.bindImp 
     908            else 
     909                _start = IntegerLit(.token.copy('INTEGER_LIT', '0'), 0).bindImp 
     910                _stop = _what 
     911            if not _step 
     912                _step = IntegerLit(.token.copy('INTEGER_LIT', '1'), 1) 
     913            _step.bindImp 
     914        else if not whatType.isDescendantOf(.compiler.enumerableType) and not whatType.isSequenceLike  # TODO: can probably drop .isSequenceLike 
    896915            .throwError('Cannot enumerate values of type "[whatType.name]". You can enumerate anything enumerable (IEnumerable, IList, arrays, strings, etc.).') 
    897916        _var = .bindVar(_nameExpr) 
    898917        if _nameExpr.definition 
     
    913932 
    914933    def inferredType as IType? is override 
    915934        assert _what.type 
    916         return _what.type.innerType 
     935        return if(_what.type inherits AnyIntType, _what.type, _what.type.innerType) 
    917936 
    918937 
    919938class IdentifierExpr 
  • Source/Cobra.Lang/Native.cs

     
    774774        return results; 
    775775    } 
    776776 
     777    /* Numeric forExpr */ 
     778    static public List<int> For<TIn, TOut>(int start, int stop, int step, ForGet<int, int> forGet) { 
     779        if ((step > 0 && start > stop) ||  
     780            (step < 0 && start < stop) || step == 0) 
     781                    throw new IndexOutOfRangeException(string.Format("ForExpr will never terminate; start={0} stop={1} step={2}",start, stop,step)); 
     782        List<int> results = new List<int>(); 
     783        for ( int item = start;  
     784            (step>0 && item < stop) || (step<0 && item > stop); 
     785            item += step)  
     786            results.Add(forGet(item)); 
     787        return results; 
     788        } 
     789    static public List<int> For<TIn, TOut>( int start, int stop, int step, ForWhereGet<int, int> forWhereGet) { 
     790        if ((step > 0 && start > stop) ||  
     791            (step < 0 && start < stop) || step == 0) 
     792                    throw new IndexOutOfRangeException(string.Format("ForExpr will never terminate; start={0} stop={1} step={2}",start, stop,step)); 
     793                List<int> results = new List<int>(); 
     794                for ( int item = start;  
     795                    (step>0 && item < stop) || (step<0 && item > stop); 
     796                    item += step) { 
     797            int value; 
     798            if (forWhereGet(item, out value)) 
     799                results.Add(value); 
     800        } 
     801        return results; 
     802    } 
     803         
    777804    static private void ProcessGetSliceArgs(int count, ref int? start, ref int? stop, ref int? step) { 
    778805        if (start==null) 
    779806            start = 0; 
  • Source/BackEndClr/SharpGenerator.cobra

     
    31103110    def writeSharpDef(sw as SharpWriter, parens as bool) is override 
    31113111        # C#:  CobraImp.For(stuff, delegate(x as int) { return x*x }) 
    31123112        # C#:  CobraImp.For(stuff, delegate(x as int) { if (x<0) return x*x; }) 
    3113         inType = _what.type.innerType 
     3113        inType = .inferredType #  _what.type.innerType 
    31143114        outType = _getExpr.type 
    31153115        sw.write('CobraImp.For<[inType.sharpRef],[outType.sharpRef]>(') 
    3116         _what.writeSharpDef(sw, false) 
     3116        if _stop 
     3117            # C#:  Numeric For Expr CobraImp.For(start, stop, step, delegate(x as int) { return x*x; }) 
     3118            _start.writeSharpDef(sw, false) 
     3119            sw.write(', ') 
     3120            _stop.writeSharpDef(sw, false) 
     3121            sw.write(', ') 
     3122            _step.writeSharpDef(sw, false) 
     3123        else 
     3124            _what.writeSharpDef(sw, false) 
    31173125        sw.write(', ') 
    31183126        helperName = '_lh_for_[_var.name]_[_varNumber]' 
    31193127        if _whereExpr is nil 
  • Source/CobraParser.cobra

     
    29442944        #   throw FallThroughException(peek)  # make C# code flow analysis happy 
    29452945        .expect('IN') 
    29462946        what = .expression 
     2947        if .optional('COLON') 
     2948            # for x in start : stop ... 
     2949            # for x in start : stop : step .... 
     2950            stopExpr = .expression 
     2951            if .optional('COLON') 
     2952                stepExpr = .expression 
    29472953        if .optional('WHERE') 
    29482954            whereExpr as Expr? = .expression 
    29492955            if .optional('GET') 
     
    29532959        else 
    29542960            .expect('GET') 
    29552961            getExpr = .expression 
    2956         return ForExpr(token, nameExpr, what, whereExpr, getExpr) 
     2962        return ForExpr(token, nameExpr, what, stopExpr, stepExpr, whereExpr, getExpr) 
    29572963 
    29582964    def identifierExpr as Expr 
    29592965        """ 
  • Tests/110-basics-two/600-functional/110-for-expr-enumerable.cobra

     
     1# for expression over enumerables 
     2class ForExprEnum 
     3    def main is shared 
     4         
     5        a = for i in [1,2,3] get i*10 
     6        assert a == [10, 20, 30] 
     7        #print a         
     8         
     9        b = for j in 'aeiou' get j 
     10        assert b == [c'a', c'e', c'i', c'o', c'u'] 
     11        #print b 
     12     
     13        c = ['how', 'now', 'brown', 'cow'] 
     14        d = for k in c where k.endsWith('ow') get k 
     15        assert d == ['how', 'now', 'cow'] 
     16         
     17        d = for k in c where not k.endsWith('ow') get k 
     18        assert d == ['brown'] 
     19         
  • Tests/110-basics-two/600-functional/111-for-expr-numeric.cobra

     
     1# for expression over numeric range 
     2class ForExprNum 
     3    def main is shared 
     4         
     5        a = for i in [1,2,3] get i*10 
     6        assert a == [10,20,30] 
     7        #print a         
     8         
     9        a = for i in 10 get i 
     10        assert a == [0,1,2,3,4,5,6,7,8,9] 
     11        #print a 
     12         
     13        a = for i in 10 where i>5 get i 
     14        assert a == [6,7,8,9] 
     15        #print a 
     16     
     17     
     18        max = 20 
     19        am = for i in max where i>15 get i 
     20        assert am == [16,17,18,19] 
     21 
     22        b = for i in 3:6 get i 
     23        assert b == [3,4,5] 
     24        #print b 
     25 
     26        b = for i in 3:6 where i>=4 get i+1 
     27        assert b == [5,6] 
     28        #print b 
     29         
     30     
     31        c = for i in 3:6:2 get i 
     32        assert c == [3,5] 
     33        #print c 
     34 
     35        c = for i in 3:8:2 where i>=4 get i+1 
     36        assert c == [6,8] 
     37        #print c 
     38         
     39         
     40        c = for i in 3:8:5 where i>=4 get i-10 
     41        assert c == [] 
     42        #print c 
     43         
     44        c = for i in 8:5:-1 get i 
     45        assert c == [8,7,6] 
     46        #print c 
     47         
     48        c = for i in 8:5:-2 get i 
     49        assert c == [8,6] 
     50     
     51        for i in 8:5:-1 
     52            print i 
     53        for i in 8:5:-2 
     54            print i 
     55 
     56        # Non terminating 
     57        expect IndexOutOfRangeException 
     58            d = for j in 8:5 get i 
     59            CobraCore.noOp(d) 
     60             
     61        # Non terminating 
     62        expect IndexOutOfRangeException 
     63            d = for j in 5:8:-1 get i 
     64            CobraCore.noOp(d) 
     65 
  • Developer/IntermediateReleaseNotes.text

     
    235235* Fixed: Cannot use `for` expressions on non-generic enumerables. ticket:85 
    236236 
    237237* Fixed: Cannot `listen` to an event when the `ref`ed method is an overload. 
     238 
     239* Fixed: for-expr enumerate int and slice-like range: ticket:71