NCPrePatcher 0.2.0-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,903 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'types.rb'
4
+ require_relative 'version.rb'
5
+
6
+ module NCPP
7
+
8
+ COMMAND_PREFIX = 'ncpp_'
9
+
10
+ class CommandRegistry < Hash
11
+ def initialize(commands, aliases: {})
12
+ @aliases = aliases
13
+ h = commands.dup
14
+
15
+ aliases.each do |alias_name, target|
16
+ h[alias_name] = h[target]
17
+ end
18
+
19
+ super()
20
+ merge!(h)
21
+ end
22
+ end
23
+
24
+ CORE_COMMANDS = CommandRegistry.new({
25
+ null: -> (*_) {}
26
+ .describe('Takes any number of arguments, does nothing with them, and returns nothing.'),
27
+
28
+ place: ->(arg) { arg }.returns(Object)
29
+ .describe('Returns the given argument as is.'),
30
+
31
+ unless: ->(out,cond,*args) { !cond ? (out.is_a?(Block) ? out.call(*args) : out) : nil }.returns(Object)
32
+ .describe('Returns or calls the given argument if the given condition is false, otherwise returns nil.'),
33
+
34
+ if: ->(out,cond,*args) { cond ? (out.is_a?(Block) ? out.call(*args) : out) : nil }.returns(Object)
35
+ .describe('Returns or calls the given argument if the given condition is true, otherwise returns nil.'),
36
+
37
+ elsif: ->(out, cond, alt_out, *args) {
38
+ out.nil? ? (cond ? (alt_out.is_a?(Block) ? alt_out.call(*args) : alt_out) : nil ) : out
39
+ }.returns(Object),
40
+ # .describe('Returns the given argument if the condition is true'),
41
+
42
+ else: ->(out, alt_out,*args) {
43
+ out.nil? ? (alt_out.is_a?(Block) ? alt_out.call(*args) : alt_out) : (out.is_a?(Block) ? out.call(*args) : out)
44
+ }.returns(Object),
45
+
46
+ then: ->(arg, block, *args) {
47
+ Utils.block_check(block, 'then')
48
+ if block.arg_names.nil?
49
+ block.call
50
+ elsif arg.nil?
51
+ block.call(*args)
52
+ else
53
+ block.call(arg, *args)
54
+ end
55
+ }.returns(Object),
56
+
57
+ do: ->(block_or_arr, *args) {
58
+ if block_or_arr.is_a?(Block) || block_or_arr.is_a?(Proc)
59
+ block_or_arr.call(*args)
60
+ elsif block_or_arr.is_a? Array
61
+ out = args[0]
62
+ block_or_arr.each do |block|
63
+ out = out.nil? ? block.call : block.call(out)
64
+ end
65
+ out
66
+ else
67
+ raise "'do' expects a Block, or an Array of Blocks"
68
+ end
69
+ }.returns(Object)
70
+ .describe("Calls the given Block with the given args, or an Array of Blocks sequentially with one arg."),
71
+
72
+ time_it: ->(block, *args) {
73
+ Utils.block_check(block, 'time_it')
74
+ start_time = Time.now
75
+ if args.nil?
76
+ block.call
77
+ else
78
+ block.call(*args)
79
+ end
80
+ Time.now - start_time
81
+ }.returns(Float).impure
82
+ .describe('Calls the given Block and gets how long it takes to execute it.'),
83
+
84
+ repeat: ->(block, count, *args) {
85
+ Utils.block_check(block, 'repeat')
86
+ if block.arg_names.nil?
87
+ count.to_i.times { block.call }
88
+ else
89
+ count.to_i.times { |i| block.call(i, *args) } # make this a separate command?
90
+ end
91
+ }.describe('Calls Block the given number of times, with the current iteration number as the first Block argument.'),
92
+
93
+ while: ->(block, cond_block) {
94
+ block.call while cond_block.call
95
+ }.describe('Repeatedly calls the given Block until the second Block returns false.'),
96
+
97
+ until: ->(block, cond_block) {
98
+ block.call until cond_block.call
99
+ }.describe('Repeatedly calls the given Block until the second Block returns true.'),
100
+
101
+ trampoline: ->(block) {
102
+ block = block.call while block.is_a?(Block)
103
+ block # not a Block at this point
104
+ }.returns(Object)
105
+ .describe(
106
+ "Calls the given Block until it no longer returns a Block. Used for calling deep recursive commands without " \
107
+ "blowing out the stack."
108
+ ),
109
+
110
+ try: ->(block, *args) {
111
+ begin
112
+ if args.nil?
113
+ block.call
114
+ else
115
+ block.call(*args)
116
+ end
117
+ rescue
118
+ nil
119
+ end
120
+ }.returns(Object).impure
121
+ .describe(
122
+ "Tries to execute and return the result of the given Block; if an exception is thrown it is caught, and nil " \
123
+ "is returned."
124
+ ),
125
+
126
+ try_or_message: ->(block, *args) {
127
+ begin
128
+ if args.nil?
129
+ block.call
130
+ else
131
+ block.call(*args)
132
+ end
133
+ rescue => e
134
+ e
135
+ end
136
+ }.returns(Object).impure
137
+ .describe(
138
+ "Tries to execute and return the result of the given Block; if an exception is thrown it is caught, and the " \
139
+ "exception message is returned."
140
+ ),
141
+
142
+ try_or: ->(block, alt) {
143
+ begin
144
+ block.call
145
+ rescue
146
+ alt.is_a?(Block) ? alt.call : alt
147
+ end
148
+ }.returns(Object).impure
149
+ .describe(
150
+ "Tries to execute the first given Block; if an exception is thrown, the second Block is executed instead."
151
+ ),
152
+
153
+ print: ->(msg, add_newline=true) {
154
+ if add_newline
155
+ puts msg
156
+ else
157
+ print msg
158
+ end
159
+ }.impure
160
+ .describe('Prints the given message, optionally ending with a newline.'),
161
+
162
+ info: ->(msg) { Utils.print_info(msg) }.impure
163
+ .describe('Prints some informative message to the console.'),
164
+
165
+ warn: ->(msg) { Utils.print_warning(msg) }.impure
166
+ .describe('Prints a warning to the console with the given message.'),
167
+
168
+ error: ->(msg) { raise msg }.impure
169
+ .describe('Raises an error with the given message.'),
170
+
171
+ breakpoint: -> { raise 'Breakpoint hit.' }.impure,
172
+
173
+ assert: ->(msg, cond) { raise msg unless cond }.impure
174
+ .describe('Raises an error with the given message if the provided condition is false.'),
175
+
176
+ type_name: ->(obj) { obj.class.to_s }.returns(String)
177
+ .describe('Gets the type name of the given object.'),
178
+
179
+ is_a: ->(obj, type_str) { obj.class.to_s == type_str }.returns(Object)
180
+ .describe('Gets whether the type of the given object matches the type described in the given String.'),
181
+
182
+ float: ->(n) { Float(n) }.returns(Float)
183
+ .describe('Gets the given argument as a Float.'),
184
+
185
+ int: ->(n) { Integer(n) }.returns(Integer)
186
+ .describe('Gets the given argument as an Integer.'),
187
+
188
+ is_even: ->(i) { i.to_i.even? }.returns(Object)
189
+ .describe('Gets whether given Integer is even.'),
190
+
191
+ is_odd: ->(i) { i.to_i.odd? }.returns(Object)
192
+ .describe('Gets whether given Integer is odd.'),
193
+
194
+ is_between: ->(n, min,max) { n.between?(min,max) }.returns(Object)
195
+ .describe('Gets whether number is between given min and max values.'),
196
+
197
+ is_nil: ->(x) { x.nil? }.returns(Object)
198
+ .describe('Gets whether given argument is nil.'),
199
+
200
+ equal: ->(x, y) { x == y }.returns(Object)
201
+ .describe('Gets whether arguments are equal.'),
202
+
203
+ not_equal: ->(x, y) { x != y }.returns(Object)
204
+ .describe('Gets whether arguments are not equal.'),
205
+
206
+ hex: ->(i) { Utils.integer_check(i,'hex'); i.to_hex }.returns(String)
207
+ .describe('Returns a hexadecimal representation of the given Integer.'),
208
+
209
+ string: ->(x) { String(x) }.returns(String)
210
+ .describe('Gets the given argument as a String.'),
211
+
212
+ upcase: ->(str) { Utils.string_check(str,'upcase'); str.upcase }.returns(String)
213
+ .describe('Gets the given String with all uppercase letters.'),
214
+
215
+ downcase: ->(str) { Utils.string_check(str,'downcase'); str.downcase }.returns(String)
216
+ .describe('Gets the given String with all lowercase letters.'),
217
+
218
+ capitalize: ->(str) { Utils.string_check(str,'capitalize'); str.capitalize }.returns(String)
219
+ .describe('Makes the first letter of the given String upcased, and the rest downcased.'),
220
+
221
+ swapcase: ->(str) { Utils.string_check(str,'swapcase'); str.swapcase }.returns(String)
222
+ .describe('Swaps the cases of each character in the given String.'),
223
+
224
+ snake_case: ->(str) {
225
+ Utils.string_check(str,'snake_case')
226
+ str.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
227
+ }.returns(String)
228
+ .describe('Gets the given String in snake_case.'),
229
+
230
+ screaming_snake_case: ->(str) {
231
+ Utils.string_check(str,'screaming_snake_case')
232
+ str.gsub(/([a-z])([A-Z])/, '\1_\2').upcase
233
+ }.returns(String)
234
+ .describe('Gets the given String in SCREAMING_SNAKE_CASE.'),
235
+
236
+ camel_case: ->(str) {
237
+ Utils.string_check(str,'camel_case')
238
+ if str.include? '_'
239
+ parts = str.split('_')
240
+ parts.first + parts[1..].map(&:capitalize).join
241
+ else
242
+ str[0].downcase + str[1..]
243
+ end
244
+ }.returns(String)
245
+ .describe('Gets the given String in camelCase.'),
246
+
247
+ pascal_case: ->(str) {
248
+ Utils.string_check(str,'pascal_case')
249
+ if str.include? '_'
250
+ parts = str.split('_')
251
+ parts.map(&:capitalize).join
252
+ else
253
+ str[0].upcase + str[1..]
254
+ end
255
+ }.returns(String)
256
+ .describe('Gets the given String in PascalCase.'),
257
+
258
+ match: ->(str, pattern_str) { Utils.string_check(str,'match'); str.match(Regexp.new(pattern_str)).to_s }
259
+ .returns(String)
260
+ .describe('Gets a String containing the portion of the given String that matches the given regex pattern.'),
261
+
262
+ matches: ->(str, pattern_str) { Utils.string_check(str,'matches'); str.match?(Regexp.new(pattern_str)) }
263
+ .returns(Object)
264
+ .describe('Gets whether a String matches the given regex pattern.'),
265
+
266
+ starts_with: ->(str,start_str) { Utils.string_check(str,'starts_with'); str.start_with?(start_str) }.returns(Object)
267
+ .describe('Gets whether String starts with other given String.'),
268
+
269
+ gsub: ->(str, pattern_str, replacement='') {
270
+ Utils.string_check(str,'gsub')
271
+ str.gsub(Regexp.new(pattern_str), replacement)
272
+ }.returns(String)
273
+ .describe('Replaces all occurences of the given pattern in the given String with the given replacement.'),
274
+
275
+ strip: ->(str) { Utils.string_check(str,'strip'); str.strip }.returns(String)
276
+ .describe('Removes leading and trailing whitespace from the given String.'),
277
+
278
+ lstrip: ->(str) { Utils.string_check(str,'lstrip'); str.lstrip }.returns(String)
279
+ .describe('Removes leading whitespace from the given String.'),
280
+
281
+ rstrip: ->(str) { Utils.string_check(str,'rstrip'); str.rstrip }.returns(String)
282
+ .describe('Removes trailing whitespace from the given String.'),
283
+
284
+ succ: ->(str) { Utils.string_check(str,'succ'); str.succ }.returns(String)
285
+ .describe('Gets the successor of a String by incrementing characters.'),
286
+
287
+ rjust: ->(str, size, pad_str=' ') { Utils.string_check(str,'rjust'); str.rjust(size,pad_str) }.returns(String)
288
+ .describe('Gets a right-justified copy of given String.'),
289
+
290
+ ljust: ->(str, size, pad_str=' ') { Utils.string_check(str,'ljust'); str.ljust(size,pad_str) }.returns(String)
291
+ .describe('Gets a left-justified copy of given String.'),
292
+
293
+ str_literal: ->(str) { '"' + str.to_s + '"' }.returns(String)
294
+ .describe('Gets the given String as a C string literal'),
295
+
296
+ raw_str_literal: ->(str) { 'R"(' + "\n" + str.to_s + ')"' }.returns(String)
297
+ .describe('Gets the given String as a C++ raw string literal.'),
298
+
299
+ add_newline: ->(str) { str.to_s + "\n" }.returns(String)
300
+ .describe('Gets the given String with an added newline at the end.'),
301
+
302
+ split: ->(str,sep=$;,limit=0) { Utils.string_check(str,'split'); str.split(sep,limit) }.returns(Array)
303
+ .describe(
304
+ "Gets an Array of substrings that are the result of splitting the given String at each occurence of the given" \
305
+ " field separator. The amount of splits are limited to the given limit (if greater than 0)."
306
+ ),
307
+
308
+ unpack: ->(byte_str, template, offset = 0) {
309
+ Utils.string_check(byte_str, 'unpack')
310
+ byte_str.unpack(template, offset: offset)
311
+ }.returns(Array)
312
+ .describe(
313
+ "Extracts data from byte String using provided template. See Ruby packed_data docs for how to format said " \
314
+ "template."
315
+ ),
316
+
317
+ pack: ->(arr, template) {
318
+ Utils.array_check(arr, 'pack')
319
+ arr.pack(template)
320
+ }.returns(String)
321
+ .describe(
322
+ "Formats elements in given Array into a binary String using provided template. See Ruby packed_data docs for " \
323
+ "how to use said template."
324
+ ),
325
+
326
+ concat: ->(obj1,obj2) { Utils.check_response(obj1,:concat); obj1.concat(obj2) }.returns(Object)
327
+ .describe('Concatenates two concatenable objects.'),
328
+
329
+ length: ->(obj) { Utils.check_response(obj,:length); obj.length }.returns(Integer)
330
+ .describe('Gets the length of the given object.'),
331
+
332
+ reverse: ->(obj) { Utils.check_response(obj,:reverse); obj.reverse }.returns(Object)
333
+ .describe('Gets the reverse of the given object.'),
334
+
335
+ is_empty: ->(obj) { Utils.check_response(obj,:empty?); obj.empty? }.returns(Object)
336
+ .describe('Gets whether the given argument is empty.'),
337
+
338
+ prepend: ->(obj, *objs) { Utils.check_response(obj,:prepend); obj.prepend(*objs) }.returns(Object),
339
+
340
+ includes: ->(obj1, obj2) { Utils.check_response(obj1, :include?); obj1.include? obj2 }.returns(Object)
341
+ .describe('Gets whether the first given object contains the second.'),
342
+
343
+ count: ->(obj,thing) {
344
+ Utils.check_response(obj,:count)
345
+ if obj.is_a?(Array) && thing.is_a?(Block)
346
+ obj.count {|idx| thing.call(idx) }
347
+ else
348
+ obj.count(thing)
349
+ end
350
+ }.returns(Integer),
351
+
352
+ slice: ->(obj, idx,len=nil) {
353
+ Utils.check_response(obj,:slice)
354
+ len.nil? ? obj.slice(idx) : obj.slice(idx,len)
355
+ }.returns(Object),
356
+
357
+ index: ->(obj,thing) {
358
+ if obj.is_a? String
359
+ obj.index(thing)
360
+ elsif obj.is_a? Array
361
+ if thing.is_a? Block
362
+ obj.index {|element| thing.call(element) }
363
+ else
364
+ obj.index(thing)
365
+ end
366
+ else
367
+ raise "'index' expects a String or an Array"
368
+ end
369
+ }.returns(Integer),
370
+
371
+ rindex: ->(obj,thing) {
372
+ if obj.is_a? String
373
+ obj.rindex(thing)
374
+ elsif obj.is_a? Array
375
+ if thing.is_a? Block
376
+ obj.rindex {|element| thing.call(element) }
377
+ else
378
+ obj.rindex(thing)
379
+ end
380
+ else
381
+ raise "'rindex' expects a String or an Array"
382
+ end
383
+ }.returns(Integer),
384
+
385
+ delete: ->(obj, thing) {
386
+ if obj.is_a? String
387
+ obj.delete(thing)
388
+ elsif obj.is_a? Array
389
+ obj.delete(thing)
390
+ obj
391
+ else
392
+ raise "'delete' expects a String or an Array"
393
+ end
394
+ }.returns(Object),
395
+
396
+ insert: ->(obj,idx,*objs) { Utils.check_response(obj,'insert'); obj.insert(idx,*objs) }.returns(Object),
397
+
398
+ array: ->(*args) { Array([*args]) }.returns(Array)
399
+ .describe('Creates an Array containing each given argument.'),
400
+
401
+ range: ->(first_or_arr,last=nil) {
402
+ if first_or_arr.is_a? Array
403
+ first = first_or_arr[0]
404
+ last = first_or_arr[1]
405
+ else
406
+ first = first_or_arr
407
+ end
408
+ (last.nil? ? 0..first : first..last).to_a
409
+ }.returns(Array),
410
+
411
+ compact: ->(arr) { Utils.array_check(arr,'compact'); arr.compact }.returns(Array)
412
+ .describe('Gets the given Array with all nil elements removed.'),
413
+
414
+ cycle: ->(arr, n, block) { Utils.array_check(arr,'cycle'); arr.cycle {|e| block.call(e) } }
415
+ .describe('Calls the given Block with each element in Array, then does so again, until it has done so n times.'),
416
+
417
+ drop: ->(arr, n) { Utils.array_check(arr,'drop'); arr.drop(n) }.returns(Array)
418
+ .describe('Gets the given Array containing all but the first n elements.'),
419
+
420
+ append: ->(arr, *objs) { Utils.array_check(arr,'append'); arr.append(*objs) }.returns(Array),
421
+ rotate: ->(arr,count=1) { Utils.array_check(arr,'rotate'); arr.rotate(count) }.returns(Array),
422
+ shuffle: ->(arr) { Utils.array_check(arr,'shuffle'); arr.shuffle }.returns(Array),
423
+ zip: ->(arr, *arrs) { Utils.array_check(arr,'zip'); arr.zip(*arrs) }.returns(Array),
424
+ flatten: ->(arr,depth=nil) { Utils.array_check(arr,'flatten'); arr.flatten(depth) }.returns(Array),
425
+ values_at: ->(arr, *specs) { Utils.array_check(arr,'values_at'); arr.values_at(*specs) }.returns(Array),
426
+ take: ->(arr,count) { Utils.array_check(arr,'take'); arr.take(count) }.returns(Array),
427
+
428
+ take_while: ->(arr,block) {
429
+ Utils.array_check(arr,'take_while')
430
+ arr.take_while {|element| block.call(element) }
431
+ }.returns(Array),
432
+
433
+ sort: ->(arr, block=nil) {
434
+ Utils.array_check(arr,'sort')
435
+ if block.nil?
436
+ arr.sort
437
+ else
438
+ arr.sort {|a,b| block.call(a,b) }
439
+ end
440
+ }.returns(Array),
441
+
442
+ sort_by: ->(arr, block) {
443
+ Utils.array_check(arr,'sort_by')
444
+ arr = arr.clone
445
+ arr.sort_by! {|e| block.call(e) }
446
+ arr
447
+ }.returns(Array),
448
+
449
+ uniq: ->(arr, block=nil) {
450
+ Utils.array_check(arr,'uniq')
451
+ if block.nil?
452
+ arr.uniq
453
+ else
454
+ arr.uniq {|e| block.call(e) }
455
+ end
456
+ }.returns(Array),
457
+
458
+ filter: ->(arr,block) {
459
+ Utils.array_check(arr,'filter')
460
+ arr.filter {|element| block.call(element) }
461
+ }.returns(Array),
462
+
463
+ map: ->(arr,block) {
464
+ Utils.array_check(arr,'map')
465
+ arr.map {|element| block.call(element) }
466
+ }.returns(Array),
467
+
468
+ flat_map: ->(arr,block) {
469
+ Utils.array_check(arr,'flat_map')
470
+ arr.flat_map {|element| block.call(element) }
471
+ }.returns(Array),
472
+
473
+ map_with_index: ->(arr,block) {
474
+ Utils.array_check(arr,'map_with_index')
475
+ arr.map.with_index {|element,i| block.call(element,i) }
476
+ }.returns(Array),
477
+
478
+ each: ->(arr,block) {
479
+ Utils.array_check(arr,'each')
480
+ arr.each {|element| block.call(element) }
481
+ },
482
+
483
+ each_with_index: ->(arr,block) {
484
+ Utils.array_check(arr,'each_with_index')
485
+ arr.each_with_index {|element,idx| block.call(element,idx) }
486
+ },
487
+
488
+ each_index: ->(arr,block) {
489
+ Utils.array_check(arr,'each_index')
490
+ arr.each_index {|idx| block.call(idx) }
491
+ },
492
+
493
+ foldl: ->(arr,init_val,block) {
494
+ Utils.array_check(arr,'foldl')
495
+ arr.inject(init_val) {|acc,n| block.call(acc,n) }
496
+ }.returns(Object),
497
+
498
+ foldr: ->(arr,init_val,block) {
499
+ Utils.array_check(arr,'foldr')
500
+ arr.reverse.inject(init_val) {|acc,n| block.call(acc,n) }
501
+ }.returns(Object),
502
+
503
+ grep: ->(arr, pattern_str, block=nil) {
504
+ if block.nil?
505
+ arr.grep(Regexp.new(pattern_str))
506
+ else
507
+ arr.grep(Regexp.new(pattern_str)) {|e| block.call(e) }
508
+ end
509
+ }.returns(Array),
510
+
511
+ grep_v: ->(arr, pattern_str, block=nil) {
512
+ if block.nil?
513
+ arr.grep_v(Regexp.new(pattern_str))
514
+ else
515
+ arr.grep_v(Regexp.new(pattern_str)) {|e| block.call(e) }
516
+ end
517
+ }.returns(Array),
518
+
519
+ fill: ->(arr, obj, start=nil, count=nil) { arr.fill(obj,start,count) }.returns(Array),
520
+ join: ->(arr, sep='') { Utils.array_check(arr,'join'); arr.join(sep) }.returns(String),
521
+ csv: ->(arr) { Utils.array_check(arr,'csv'); arr.join(',') }.returns(String),
522
+ from_csv: ->(str) { Utils.string_check(str,'from_csv'); str.split(',') }.returns(Array),
523
+ at: ->(arr,i) { Utils.array_check(arr,'at'); arr.at(i) }.returns(Object),
524
+ first: ->(arr) { Utils.array_check(arr,'first'); arr[0] }.returns(Object),
525
+ last: ->(arr) { Utils.array_check(arr,'last'); arr[-1] }.returns(Object),
526
+ max: ->(arr) { Utils.array_check(arr,'max'); arr.max }.returns(Object),
527
+ min: ->(arr) { Utils.array_check(arr,'min'); arr.min }.returns(Object),
528
+ minmax: ->(arr) { Utils.array_check(arr,'minmax'); arr.minmax }.returns(Array),
529
+ sum: ->(arr,init=0) { Utils.array_check(arr,'sum'); arr.sum(init) }.returns(Integer),
530
+ to_c_array: ->(arr) { Utils.to_c_array(arr) }.returns(String),
531
+
532
+ max_by: ->(arr, block) {
533
+ Utils.array_check(arr,'max_by')
534
+ arr.max_by {|e| block.call(e) }
535
+ }.returns(Object),
536
+
537
+ min_by: ->(arr, block) {
538
+ Utils.array_check(arr,'min_by')
539
+ arr.min_by {|e| block.call(e) }
540
+ }.returns(Object),
541
+
542
+ sample: ->(arr, count=nil) {
543
+ Utils.array_check(arr, 'sample')
544
+ count.nil? ? arr.sample : arr.sample(count)
545
+ }.returns(Object).impure
546
+ .describe('Gets a random element of the given array.'),
547
+
548
+ year: -> { Time.now.year }.returns(Integer) .impure.describe('Gets the current year.'),
549
+ month: -> { Time.now.month }.returns(Integer).impure.describe('Gets the current month.'),
550
+ day: -> { Time.now.day }.returns(Integer) .impure.describe('Gets the current day.'),
551
+ hour: -> { Time.now.hour }.returns(Integer) .impure.describe('Gets the current hour.'),
552
+ minute: -> { Time.now.min }.returns(Integer) .impure.describe('Gets the current minute.'),
553
+ second: -> { Time.now.sec }.returns(Integer) .impure.describe('Gets the current second.'),
554
+
555
+ rand: ->(n1=nil,n2=nil) {
556
+ if n1.is_a? Array
557
+ if n2.nil? || !n2.is_a?(Integer)
558
+ n1.sample
559
+ else
560
+ n1.sample(n2)
561
+ end
562
+ else
563
+ n1.nil? ? Random.rand() : (n2.nil? ? Random.rand(n1) : Random.rand(n1..n2))
564
+ end
565
+ }.returns(Object).impure,
566
+
567
+ sub: ->(n_or_arr,n_or_pattern,replacement='') {
568
+ if n_or_arr.is_a? Numeric
569
+ n_or_arr - n_or_pattern
570
+ else
571
+ n_or_arr.sub(n_or_pattern,replacement)
572
+ end
573
+ }.returns(Object)
574
+ .describe(
575
+ "Subtracts two numbers, or, if an Array is given, replaces the first occurence of the given pattern with the "\
576
+ "given replacement."
577
+ ),
578
+
579
+ add: ->(a,b) { a + b }.returns(Object).describe('Adds two objects.'),
580
+ mul: ->(a,b) { a * b }.returns(Numeric).describe('Multiplies two numbers.'),
581
+ div: ->(a,b) { a / b }.returns(Numeric).describe('Divides two numbers.'),
582
+ mod: ->(a,b) { a % b }.returns(Numeric).describe('Gets the modulo of two numbers.'),
583
+ abs: ->(n) { n.abs }.returns(Numeric).describe('Gets the absolute value of the given number.'),
584
+ sin: ->(n) { Math.sin(n) }.returns(Float).describe('Gets the sine of the given number in radians.'),
585
+ cos: ->(n) { Math.cos(n) }.returns(Float).describe('Gets the cosine of the given number in radians.'),
586
+ tan: ->(n) { Math.tan(n) }.returns(Float).describe('Gets the tangent of the given number in radians.'),
587
+ exp: ->(n) { Math.exp(n) }.returns(Float).describe('Gets e raised to the power of the given number.'),
588
+ log: ->(n) { Math.log(n) }.returns(Float).describe('Gets the base logarithm of the given number.'),
589
+ sqrt: ->(n) { Math.sqrt(n) }.returns(Float).describe('Gets the square root of the given number.'),
590
+ clamp: ->(n, min,max=nil) { n.clamp(min,max) }.returns(Numeric)
591
+ .describe('Clamps number between given min and max values.'),
592
+
593
+ over: ->(addr_or_sym,ov=nil) { Utils.gen_hook_str('over', addr_or_sym, ov) }.returns(String)
594
+ .describe(Utils.gen_hook_description('over')),
595
+ hook: ->(addr_or_sym,ov=nil) { Utils.gen_hook_str('hook', addr_or_sym, ov) }.returns(String)
596
+ .describe(Utils.gen_hook_description('hook')),
597
+ call: ->(addr_or_sym,ov=nil) { Utils.gen_hook_str('call', addr_or_sym, ov) }.returns(String)
598
+ .describe(Utils.gen_hook_description('call')),
599
+ jump: ->(addr_or_sym,ov=nil) { Utils.gen_hook_str('jump', addr_or_sym, ov) }.returns(String)
600
+ .describe(Utils.gen_hook_description('jump')),
601
+ thook: ->(addr_or_sym,ov=nil) { Utils.gen_hook_str('thook', addr_or_sym, ov) }.returns(String)
602
+ .describe(Utils.gen_hook_description('thook')),
603
+ tcall: ->(addr_or_sym,ov=nil) { Utils.gen_hook_str('tcall', addr_or_sym, ov) }.returns(String)
604
+ .describe(Utils.gen_hook_description('tcall')),
605
+ tjump: ->(addr_or_sym,ov=nil) { Utils.gen_hook_str('tjump', addr_or_sym, ov) }.returns(String)
606
+ .describe(Utils.gen_hook_description('tjump')),
607
+
608
+ set_hook: ->(addr,ov,fn=nil) { Utils.gen_set_hook_str('set_hook', addr, ov, fn) }
609
+ .returns(String).ignore_unk_var_at_arg(1,2),
610
+
611
+ set_call: ->(addr,ov,fn=nil) { Utils.gen_set_hook_str('set_call', addr, ov, fn) }
612
+ .returns(String).ignore_unk_var_at_arg(1,2),
613
+
614
+ set_jump: ->(addr,ov,fn=nil) { Utils.gen_set_hook_str('set_jump', addr, ov, fn) }
615
+ .returns(String).ignore_unk_var_at_arg(1,2),
616
+
617
+ set_thook: ->(addr,ov,fn=nil) { Utils.gen_set_hook_str('set_thook', addr, ov, fn) }
618
+ .returns(String).ignore_unk_var_at_arg(1,2),
619
+
620
+ set_tcall: ->(addr,ov,fn=nil) { Utils.gen_set_hook_str('set_tcall', addr, ov, fn) }
621
+ .returns(String).ignore_unk_var_at_arg(1,2),
622
+
623
+ set_tjump: ->(addr,ov,fn=nil) { Utils.gen_set_hook_str('set_tjump', addr, ov, fn) }
624
+ .returns(String).ignore_unk_var_at_arg(1,2),
625
+
626
+ repl: ->(addr, ov_or_asm, asm=nil) {
627
+ Utils.gen_hook_str('repl', addr, ov_or_asm.is_a?(String) ? nil : ov_or_asm, asm.nil? ? ov_or_asm : asm)
628
+ }.returns(String),
629
+
630
+ trepl: ->(addr, ov_or_asm, asm=nil) {
631
+ 'ncp_thumb ' +
632
+ Utils.gen_hook_str('repl', addr, ov_or_asm.is_a?(String) ? nil : ov_or_asm, asm.nil? ? ov_or_asm : asm)
633
+ }.returns(String),
634
+
635
+ over_guard: ->(loc,ov=nil) { Utils.gen_c_over_guard(loc, ov) }.returns(String),
636
+
637
+ over_func: ->(loc,ov=nil) {
638
+ addr, ov = Utils.resolve_loc(loc,ov)
639
+ Utils.gen_c_over_guard(addr + Utils.get_function_size(addr,ov),ov) + "\n\n" + Utils.gen_hook_str('over', addr,ov)
640
+ }.returns(String),
641
+
642
+ repl_imm: ->(loc, ov, val) { Utils.modify_ins_immediate(loc, ov, val) }.returns(String)
643
+ .describe("Modifies the immediate in the instruction at the given address by generating a 'repl' hook using " \
644
+ "the original ASM with the immediate swapped to the value given."),
645
+
646
+ repl_array: ->(loc, ov, dtype, arr) { Utils.gen_repl_array(loc,ov,dtype,arr) }.returns(String),
647
+
648
+ repl_u64_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :u64, arr) }.returns(String),
649
+ repl_s64_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :s64, arr) }.returns(String),
650
+ repl_u32_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :u32, arr) }.returns(String),
651
+ repl_s32_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :s32, arr) }.returns(String),
652
+ repl_u16_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :u16, arr) }.returns(String),
653
+ repl_s16_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :s16, arr) }.returns(String),
654
+ repl_u8_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :u8, arr) }.returns(String),
655
+ repl_s8_array: ->(loc,ov_or_arr,arr=nil) { Utils.gen_repl_type_array(loc, ov_or_arr, :s8, arr) }.returns(String),
656
+
657
+ hex_edit: ->(ov, og_hex_str, new_hex_str) { Utils.gen_hex_edit(ov, og_hex_str, new_hex_str) }.returns(String),
658
+
659
+ code_loc: ->(loc,ov=nil) { CodeLoc.new(loc, ov) }.returns(CodeLoc), # Will this ever be properly implemented? TBD
660
+ next_addr: ->(current_addr,ov=nil) { Utils.next_addr(current_addr,ov) }.returns(Integer),
661
+ addr_to_sym: ->(addr,ov=nil) { Utils.addr_to_sym(addr, ov) }.returns(String),
662
+ sym_to_addr: ->(sym) { Utils.sym_to_addr(sym) }.returns(Integer),
663
+ get_sym_ov: ->(sym) { Utils.get_sym_ov(sym) }.returns(Integer),
664
+ sym_from_index: ->(idx) { Unarm.sym_map.to_a[idx][0] }.returns(String),
665
+ demangle: ->(sym) { Unarm.shitty_demangle(sym) }.returns(String),
666
+
667
+ get_function: ->(addr,ov=nil) { Utils.get_reloc_func(addr, ov) }.returns(String),
668
+ get_instruction: ->(addr,ov=nil) { Utils.get_instruction(addr, ov) }.returns(String),
669
+ get_reloc_instruction: ->(addr,ov=nil) { Utils.get_raw_instruction(addr, ov).str }.returns(String),
670
+ get_dword: ->(addr,ov=nil) { Utils.get_dword(addr,ov) }.returns(Integer),
671
+ get_word: ->(addr,ov=nil) { Utils.get_word(addr,ov) }.returns(Integer),
672
+ get_hword: ->(addr,ov=nil) { Utils.get_hword(addr,ov) }.returns(Integer),
673
+ get_byte: ->(addr,ov=nil) { Utils.get_byte(addr,ov) }.returns(Integer),
674
+ get_signed_dword: ->(addr,ov=nil) { Utils.get_signed_dword(addr,ov) }.returns(Integer),
675
+ get_signed_word: ->(addr,ov=nil) { Utils.get_signed_word(addr,ov) }.returns(Integer),
676
+ get_signed_hword: ->(addr,ov=nil) { Utils.get_signed_hword(addr,ov) }.returns(Integer),
677
+ get_signed_byte: ->(addr,ov=nil) { Utils.get_signed_byte(addr,ov) }.returns(Integer),
678
+ get_cstring: ->(addr,ov=nil) { Utils.get_cstring(addr,ov) }.returns(String),
679
+ get_array: ->(addr,ov,e_type_id,e_count=1) { Utils.get_array(addr,ov,e_type_id,e_count) }.returns(Array),
680
+
681
+ get_c_array: ->(addr,ov,e_type_id,e_count=1) {
682
+ Utils.to_c_array(Utils.get_array(addr,ov,e_type_id,e_count))
683
+ }.returns(Array),
684
+
685
+ find_first_branch_to: ->(branch_dest, start_loc,start_ov=nil) {
686
+ Utils.find_branch_to(branch_dest, start_loc,start_ov)
687
+ }.returns(Integer),
688
+
689
+ find_first_branch_to_in_func: ->(branch_dest, func_loc,func_ov=nil) {
690
+ Utils.find_branch_to(branch_dest, func_loc,func_ov, from_func: true)
691
+ }.returns(Integer),
692
+
693
+ in_func_find_first_branch_to: ->(func_loc,func_ov, branch_dest) {
694
+ Utils.find_branch_to(branch_dest, func_loc,func_ov, from_func: true)
695
+ }.returns(Integer),
696
+
697
+ find_branches_to_in_func: ->(branch_dest, func_loc,func_ov=nil) {
698
+ Utils.find_branch_to(branch_dest, func_loc,func_ov, from_func: true, find_all: true)
699
+ }.returns(Array),
700
+
701
+ in_func_find_branches_to: ->(func_loc,func_ov, branch_dest) {
702
+ Utils.find_branch_to(branch_dest, func_loc,func_ov, from_func: true, find_all: true)
703
+ }.returns(Array),
704
+
705
+ track_reg: ->(reg, from_addr,ov, to_addr) { Utils.track_reg(reg, from_addr,ov, to_addr) }.returns(String),
706
+
707
+ find_ins_in_func: ->(ins_pattern_str, func_loc,func_ov=nil) {
708
+ Utils.find_ins_in_func(ins_pattern_str,func_loc,func_ov)
709
+ }.returns(Integer),
710
+
711
+ get_ins_mnemonic: ->(loc,ov=nil) { Utils.get_ins_mnemonic(loc,ov) }.returns(String),
712
+ get_ins_arg: ->(loc,ov,arg_index) { Utils.get_ins_arg(loc,ov,arg_index) }.returns(String),
713
+ get_ins_branch_dest: ->(loc,ov=nil) { Utils.get_ins_branch_dest(loc,ov) }.returns(Integer),
714
+ get_ins_target_addr: ->(loc,ov=nil) { Utils.get_ins_target_addr(loc,ov) }.returns(Integer),
715
+
716
+ get_function_literal_pool: ->(loc,ov=nil) { Utils.get_func_literal_pool(loc,ov) }.returns(String)
717
+ .describe('Gets the literal pool of the given function as a String of ASM.'),
718
+
719
+ get_function_literal_pool_values: ->(loc,ov=nil) {
720
+ Utils.get_func_literal_pool_values(loc,ov)
721
+ }.returns(Array)
722
+ .describe('Gets the literal pool values of the given function as an Array of integers.'),
723
+
724
+ get_function_literal_pool_addresses: ->(loc,ov=nil) {
725
+ Utils.get_func_literal_pool_addrs(loc,ov)
726
+ }.returns(Array)
727
+ .describe('Gets an Array containing the addresses of each literal pool entry of the given function.'),
728
+
729
+ get_function_size: ->(loc,ov=nil) { Utils.get_function_size(loc,ov) }.returns(Integer)
730
+ .describe('Gets the size of the function at the given location. Includes the literal pool.'),
731
+
732
+ disasm_arm_ins: ->(data) { Utils.disasm_arm_ins(data) }.returns(String),
733
+ disasm_thumb_ins: ->(data) { Utils.disasm_thumb_ins(data) }.returns(String),
734
+
735
+ disasm_arm_hex_seq: ->(hex_byte_str) { Utils.disasm_hex_seq(hex_byte_str) }.returns(Array),
736
+ disasm_thumb_hex_seq: ->(hex_byte_str) { Utils.disasm_hex_seq(hex_byte_str) }.returns(Array),
737
+
738
+ is_address_in_overlay: ->(addr, ov) { Utils.addr_in_overlay?(addr, ov) }.returns(Object)
739
+ .describe('Gets whether the given address is in the given overlay.'),
740
+
741
+ is_address_in_arm9: ->(addr) { Utils.addr_in_arm9?(addr) }.returns(Object)
742
+ .describe('Gets whether the given address is in ARM9.'),
743
+
744
+ is_address_in_arm7: ->(addr) { Utils.addr_in_arm7?(addr) }.returns(Object)
745
+ .describe('Gets whether the given address is in ARM7.'),
746
+
747
+ find_hex_bytes: ->(ov, hex_str) { Utils.find_hex_bytes(ov,hex_str) }.returns(Integer),
748
+
749
+ fx64: ->(n) { (n * (1 << 12)).round().signed(64) }.returns(Integer)
750
+ .describe('Gets the given number as an fx64 (an s51.12 fixed point number).'),
751
+
752
+ from_fx64: ->(n) { n.signed(64) / Float(1 << 12) }.returns(Float)
753
+ .describe('Gets the given fx64 number as a Float.'),
754
+
755
+ fx32: ->(n) { (n * (1 << 12)).round().signed(32) }.returns(Integer)
756
+ .describe('Gets the given number as an fx32 (an s19.12 fixed point number).'),
757
+
758
+ from_fx32: ->(n) { n.signed(32) / Float(1 << 12) }.returns(Float)
759
+ .describe('Gets the given fx32 number as a Float.'),
760
+
761
+ fx16: ->(n) { (n * (1 << 12)).round().signed(16) }.returns(Integer)
762
+ .describe('Gets the given number as an fx16 (an s3.12 fixed point number).'),
763
+
764
+ from_fx16: ->(n) { n.signed(16) / Float(1 << 12) }.returns(Float)
765
+ .describe('Gets the given fx16 number as a Float.'),
766
+
767
+ u64: ->(n) { n.unsigned(64) }.returns(Integer).describe('Gets the given number as an unsigned 64-bit Integer.'),
768
+ s64: ->(n) { n.signed(64) }.returns(Integer).describe('Gets the given number as a signed 64-bit Integer.'),
769
+ u32: ->(n) { n.unsigned(32) }.returns(Integer).describe('Gets the given number as an unsigned 32-bit Integer.'),
770
+ s32: ->(n) { n.signed(32) }.returns(Integer).describe('Gets the given number as a signed 32-bit Integer.'),
771
+ u16: ->(n) { n.unsigned(16) }.returns(Integer).describe('Gets the given number as an unsigned 16-bit Integer.'),
772
+ s16: ->(n) { n.signed(16) }.returns(Integer).describe('Gets the given number as a signed 16-bit Integer.'),
773
+ u8: ->(n) { n.unsigned(8) }.returns(Integer).describe('Gets the given number as an unsigned 8-bit Integer.'),
774
+ s8: ->(n) { n.signed(8) }.returns(Integer).describe('Gets the given number as a signed 8-bit Integer.'),
775
+
776
+ from_fx_deg: ->(fx_num) {
777
+ Float(fx_num) / 0x10000 * 360
778
+ }.returns(Float),
779
+
780
+ fx_deg: ->(n) {
781
+ if n < 0
782
+ n -= 360 while n >= 360
783
+ else
784
+ n += 360 while n < 0
785
+ end
786
+ (n * 0x10000 / 360).signed(16)
787
+ }.returns(Integer),
788
+
789
+ gx_rgb: ->(r,g,b) { ((r << 0) | (g << 5) | (b << 10)).unsigned(16) }.returns(Integer)
790
+ .describe('Packs the given values into an RGB x1B5G5R5 format 16-bit unsigned integer.'),
791
+ gx_rgba: ->(r,g,b,a) { ((r << 0) | (g << 5) | (b << 10) | (a << 15)).unsigned(16) }.returns(Integer)
792
+ .describe('Packs the given values into an RGB A1B5G5R5 format 16-bit unsigned integer.'),
793
+
794
+ from_gx_rgb: ->(n) { [(n >> 0) & 31, (n >> 5) & 31, (n >> 10) & 31] }.returns(Array)
795
+ .describe('Unpacks the given RGB x1B5G5R5 value as an Array ([R,G,B]).'),
796
+ from_gx_rgba: ->(n) { [(n >> 0) & 31, (n >> 5) & 31, (n >> 10) & 31, (n >> 15) & 1] }.returns(Array)
797
+ .describe('Unpacks the given packed RGB A1B5G5R5 value as an Array ([R,G,B,A]).')
798
+
799
+ },
800
+
801
+ aliases: {
802
+ snuff: :null,
803
+ discard: :null,
804
+ _: :place,
805
+ try_or_msg: :try_or_message,
806
+ tramp: :trampoline,
807
+ eql: :equal,
808
+ equals: :equal,
809
+ size: :length,
810
+ str: :string,
811
+ integer: :int,
812
+ upper: :upcase,
813
+ lower: :downcase,
814
+ capitalise: :capitalize,
815
+ quoted: :str_literal,
816
+ del: :delete,
817
+ to_hex: :hex,
818
+ is_null: :is_nil,
819
+ len: :length,
820
+ contains: :includes,
821
+ map_with_idx: :map_with_index,
822
+ each_with_idx: :each_with_index,
823
+ each_idx: :each_index,
824
+ find_all: :filter,
825
+ reduce: :foldr,
826
+ inject: :foldr,
827
+ random: :rand,
828
+ get_func: :get_function,
829
+ get_ins: :get_instruction,
830
+ get_reloc_ins: :get_reloc_instruction,
831
+ get_u64: :get_dword,
832
+ get_s64: :get_signed_dword,
833
+ get_u32: :get_word,
834
+ get_s32: :get_word,
835
+ get_int: :get_word,
836
+ get_u16: :get_hword,
837
+ get_s16: :get_signed_hword,
838
+ get_u8: :get_byte,
839
+ get_s8: :get_signed_byte,
840
+ get_cstr: :get_cstring,
841
+ disasm_ins: :disasm_arm_ins,
842
+ disasm_hex_seq: :disasm_arm_hex_seq,
843
+ disasm_hex_str: :disasm_arm_hex_seq,
844
+ disasm_arm_hex_str: :disasm_arm_hex_seq,
845
+ disasm_thumb_hex_str: :disasm_thumb_hex_seq,
846
+ sym_to_ov: :get_sym_ov,
847
+ get_address: :sym_to_addr,
848
+ get_addr: :sym_to_addr,
849
+ get_symbol: :addr_to_sym,
850
+ get_sym: :addr_to_sym,
851
+ get_arr: :get_array,
852
+ to_c_arr: :to_c_array,
853
+ mod_imm: :repl_imm,
854
+ repl_arr: :repl_array,
855
+ repl_fx32_arr: :repl_s32_array,
856
+ repl_fx16_arr: :repl_s16_array,
857
+ repl_u64_arr: :repl_u64_array,
858
+ repl_s64_arr: :repl_s64_array,
859
+ repl_u32_arr: :repl_u32_array,
860
+ repl_s32_arr: :repl_s32_array,
861
+ repl_u16_arr: :repl_u16_array,
862
+ repl_s16_arr: :repl_s16_array,
863
+ repl_u8_arr: :repl_u8_array,
864
+ repl_s8_arr: :repl_s8_array,
865
+ repl_fx32_array: :repl_s32_array,
866
+ repl_fx16_array: :repl_s16_array,
867
+ get_func_literal_pool: :get_function_literal_pool,
868
+ get_func_lit_pool: :get_function_literal_pool,
869
+ get_func_literal_pool_values: :get_function_literal_pool_values,
870
+ get_func_lit_pool_vals: :get_function_literal_pool_values,
871
+ get_func_literal_pool_addrs: :get_function_literal_pool_addresses,
872
+ get_func_lit_pool_addrs: :get_function_literal_pool_addresses,
873
+ get_func_size: :get_function_size,
874
+ get_ins_load_addr: :get_ins_target_addr,
875
+ is_addr_in_overlay: :is_address_in_overlay,
876
+ is_addr_in_ov: :is_address_in_overlay,
877
+ is_addr_in_arm9: :is_address_in_arm9,
878
+ is_addr_in_arm7: :is_address_in_arm7,
879
+ find_hex_seq: :find_hex_bytes
880
+ }).freeze
881
+
882
+
883
+ CORE_VARIABLES = {
884
+ NCPP_VERSION: VERSION,
885
+ BUILD_DATE: Time.now.to_s,
886
+ PI: Math::PI,
887
+ EOL: "\n",
888
+ TAB: "\t",
889
+ u64: Utils::DTYPE_IDS[:u64],
890
+ u32: Utils::DTYPE_IDS[:u32],
891
+ u16: Utils::DTYPE_IDS[:u16],
892
+ u8: Utils::DTYPE_IDS[:u8],
893
+ s64: Utils::DTYPE_IDS[:s64],
894
+ s32: Utils::DTYPE_IDS[:s32],
895
+ fx32: Utils::DTYPE_IDS[:s32],
896
+ s16: Utils::DTYPE_IDS[:s16],
897
+ fx16: Utils::DTYPE_IDS[:s16],
898
+ s8: Utils::DTYPE_IDS[:s8],
899
+ ARM9: -1,
900
+ ARM7: -2
901
+ }.freeze
902
+
903
+ end