JockoDundee Posted December 8, 2020 Share Posted December 8, 2020 1 hour ago, Nine said: Then use my slow script : Shift is always the ballbuster, eh? TheDcoder 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Nine Posted December 8, 2020 Share Posted December 8, 2020 1 hour ago, JockoDundee said: Shift is always the ballbuster, eh? I tried once to make it recursive, that was a 2B-buster...Brain and Balls TheDcoder and JockoDundee 2 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text  Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker  Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC  HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet  Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector  Printer Manager GIF Animation (cached)  Screen Scraping   Multi-Threading Made Easy   Link to comment Share on other sites More sharing options...
rcmaehl Posted December 8, 2020 Share Posted December 8, 2020 22 hours ago, Nine said: Then use my slow script :  Reveal hidden contents expandcollapse popupFunc _BitAND64($iValue1, $iValue2) If VarGetType($iValue1) <> "Int64" And VarGetType($iValue2) <> "Int64" Then Return BitAND($iValue1, $iValue2) $iValue1 = __DecToBin64($iValue1) $iValue2 = __DecToBin64($iValue2) Local $aValueANDed[64] For $i = 0 To 63 $aValueANDed[$i] = ($iValue1[$i] And $iValue2[$i]) ? 1 : 0 Next Return __BinToDec64($aValueANDed) EndFunc ;==>_BitAND64 Func _BitOR64($iValue1, $iValue2) If VarGetType($iValue1) <> "Int64" And VarGetType($iValue2) <> "Int64" Then Return BitOR($iValue1, $iValue2) $iValue1 = __DecToBin64($iValue1) $iValue2 = __DecToBin64($iValue2) Local $aValueORed[64] For $i = 0 To 63 $aValueORed[$i] = ($iValue1[$i] Or $iValue2[$i]) ? 1 : 0 Next Return __BinToDec64($aValueORed) EndFunc ;==>_BitOR64 Func _BitXOR64($iValue1, $iValue2) If VarGetType($iValue1) <> "Int64" And VarGetType($iValue2) <> "Int64" Then Return BitXOR($iValue1, $iValue2) $iValue1 = __DecToBin64($iValue1) $iValue2 = __DecToBin64($iValue2) Local $aValueXORed[64] For $i = 0 To 63 $aValueXORed[$i] = (($iValue1[$i] And (Not $iValue2[$i])) Or ((Not $iValue1[$i]) And $iValue2)) ? 1 : 0 Next Return __BinToDec64($aValueXORed) EndFunc ;==>_BitXOR64 Func _BitNOT64($iValue) If Not VarGetType($iValue) = "Int64" Then Return BitNOT($iValue) $iValue = __DecToBin64($iValue) For $i = 0 To 63 $iValue[$i] = Not $iValue[$i] Next Return __BinToDec64($iValue) EndFunc ;==>_BitNOT64 Func _BitRotate64($iValue, $iShift) If VarGetType($iValue) <> "Int64" Then Return BitRotate($iValue, $iShift, "D") $iValue = __DecToBin64($iValue) Local $iTmp If $iShift < 0 Then ; rotate right For $i = 1 To Abs($iShift) $iTmp = $iValue[0] For $j = 1 To 63 $iValue[$j - 1] = $iValue[$j] Next $iValue[63] = $iTmp Next Else For $i = 1 To $iShift $iTmp = $iValue[63] For $j = 63 To 1 Step -1 $iValue[$j] = $iValue[$j - 1] Next $iValue[0] = $iTmp Next EndIf Return __BinToDec64($iValue) EndFunc ;==>_BitRotate64 Func _BitShift64($iValue, $iShift, $bSigned = True) If $iShift <= 0 Then $bSigned = True If VarGetType($iValue) <> "Int64" Then If $bSigned Then Return BitShift($iValue, $iShift) If $iShift > 0 Then $iValue = BitAND(BitShift($iValue, 1), 0x7FFFFFFF) Return BitShift($iValue, $iShift-1) EndIf EndIf $iValue = __DecToBin64($iValue) Local $iTmp If $iShift > 0 Then ; shift right $iTmp = $bSigned ? $iValue[63] : 0 For $i = 1 To Abs($iShift) For $j = 1 To 63 $iValue[$j - 1] = $iValue[$j] Next $iValue[63] = $iTmp Next Else For $i = 1 To Abs($iShift) For $j = 63 To 1 Step -1 $iValue[$j] = $iValue[$j - 1] Next $iValue[0] = 0 Next EndIf Return __BinToDec64($iValue) EndFunc ;==>_BitShift64 Func __DecToBin64($iDec) Local $tI64 = DllStructCreate("int64 num"), $aBin[64], $iVal Local $tI32 = DllStructCreate("align 4;uint low;uint high", DllStructGetPtr($tI64)) $tI64.num = $iDec For $i = 0 To 31 $iVal = 2 ^ $i $aBin[$i] = BitAND($tI32.low, $iVal) ? 1 : 0 $aBin[$i + 32] = BitAND($tI32.high, $iVal) ? 1 : 0 Next Return $aBin EndFunc ;==>__DecToBin64 Func __BinToDec64($aBin) Local $tI32 = DllStructCreate("align 4;uint low;uint high"), $iVal Local $tI64 = DllStructCreate("UINT64 num", DllStructGetPtr($tI32)) For $i = 0 To 31 $iVal = 2 ^ $i $tI32.low += $aBin[$i] ? $iVal : 0 $tI32.high += $aBin[$i + 32] ? $iVal : 0 Next Return $tI64.num EndFunc ;==>__BinToDec64   THANK YOU!!!! I got code working for variable length bits (specifically for BitNOT) up to 48 bits but this will work! TheDcoder 1 My UDFs are generally for me. If they aren't updated for a while, it means I'm not using them myself. As soon as I start using them again, they'll get updated.My Projects WhyNotWin11Cisco Finesse, Github, IRC UDF, WindowEx UDF  Link to comment Share on other sites More sharing options...
Nine Posted December 8, 2020 Share Posted December 8, 2020 (edited) 17 hours ago, rcmaehl said: THANK YOU!!!! lol, glad you like it  Should work up to 64 bits, doesn't it ? ps. corrected a small bug on XOR, code has been updated Edited December 9, 2020 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text  Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker  Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC  HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet  Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector  Printer Manager GIF Animation (cached)  Screen Scraping   Multi-Threading Made Easy   Link to comment Share on other sites More sharing options...
JockoDundee Posted December 10, 2020 Share Posted December 10, 2020 On 12/7/2020 at 2:46 PM, Nine said: Then use my slow script : Possibly the Fastest 64Bit Bitwise NOT ever: Func _NotABit($iInt) Return -$iInt-1 EndFunc  TheDcoder 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
TheDcoder Posted December 14, 2020 Author Share Posted December 14, 2020 To prevent this topic from turning into a discussion on bitwise operations, I will post an update on the progress In the last updated I showed off the parser I wrote... unfortunately it turns out it isn't capable of handling pretty much anything other than infix binary operators . So I had to go back and start from scratch, I read many articles again to see how they handled expressions, the problem with these articles is that they use object-oriented programming which is hard to follow... so it took me a long time to finally grasp the concept driving all the recursive decent parsers I had been reading about. So I wrote my own parser in JavaScript as a proof of concept, I chose JS because I am familiar with it and it is easier to write high-level code in it, not to mention that it runs in any computer with a browser. Here is the code: expandcollapse popup/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ const TokenType = { CONSTANT: Symbol("Constant"), OPERATOR: Symbol("Operator"), BRACKET: Symbol("Bracket"), }; const Operation = { INVERT: Symbol("Invert"), NEGATE: Symbol("Negate"), ADD: Symbol("Add"), SUBTRACT: Symbol("Subtract"), MULTIPLY: Symbol("Multiply"), DIVIDE: Symbol("Divide"), EXPONENTIATE: Symbol("Exponentiate"), ASSIGN: Symbol("Assign"), SINE: Symbol("Sin"), LOG: Symbol("Log"), }; const Precedence = [ [Operation.INVERT], [Operation.NEGATE], [ Operation.SINE, Operation.LOG ], [Operation.EXPONENTIATE], [ Operation.MULTIPLY, Operation.DIVIDE, ], [ Operation.ADD, Operation.SUBTRACT, ], [Operation.ASSIGN], ]; Precedence.reverse(); // IMPORTANT Precedence.next = op => Precedence.find(a => a.includes(op)) + 1; const OP_MAP = new Map([ ['!', Operation.NEGATE], ['+', Operation.ADD], ['-', Operation.SUBTRACT], ['*', Operation.MULTIPLY], ['/', Operation.DIVIDE], ['^', Operation.EXPONENTIATE], ['=', Operation.ASSIGN], ['s', Operation.SINE], ['l', Operation.LOG], ]); if (globalThis.process) main(process.argv); function main(args) { const input = args[2]; if (!input) { console.error("No arguments supplied!"); return; } var tokens = tokenize(input); var expression = parse(tokens); expression.raw = input; var output = JSON.stringify(expression, (key, value) => { if (typeof value == 'symbol') return value.description; return value; }, '\t'); console.log(output); return output; } function tokenize(input) { var tokens = []; var constant; for (let i = 0; i < input.length; ++i) { // Parse constants (numbers) constant = ""; while (true) { if (isNaN(parseInt(input[i], 10))) { if (constant) --i; break; } constant += input[i++]; } if (constant) { tokens.push({type: TokenType.CONSTANT, value: parseInt(constant, 10)}); continue; } // Parse operators if (OP_MAP.has(input[i])) { tokens.push({type: TokenType.OPERATOR, value: OP_MAP.get(input[i])}); continue; } // Parse brackets if (input[i] == '(' || input[i] == ')') { tokens.push({type: TokenType.BRACKET, value: {open: input[i] == '('}}); continue; } // Skip whitespace if (input[i] == ' ') continue; // Unknown token, so break out of the loop break; } return tokens; } function parse(tokens, precedence = 0) { var expression = {op: undefined, args: []}; // Unpack a sub-expression (remove the surrounding brackets) if (tokens[0].type == TokenType.BRACKET && tokens[tokens.length - 1].type == TokenType.BRACKET) tokens = tokens.slice(1, tokens.length - 1); switch (Precedence[precedence] ? Precedence[precedence][0] : undefined) { case Operation.INVERT: if (tokens[0].value == Operation.SUBTRACT) { expression.op = Operation.INVERT; push_sub_exp_as_arg(1); } else return next(); break; case Operation.NEGATE: if (tokens[0].type == (expression.op = Operation.NEGATE)) { push_sub_exp_as_arg(1); } else return next(); break; case Operation.SINE: case Operation.LOG: if ( (tokens[tokens.length - 1].value == (expression.op = Operation.SINE)) || (tokens[tokens.length - 1].value == (expression.op = Operation.LOG)) ) { push_sub_exp_as_arg(0, -1); } else return next(); break; case Operation.EXPONENTIATE: case Operation.MULTIPLY: case Operation.DIVIDE: case Operation.ADD: case Operation.SUBTRACT: case Operation.ASSIGN: parse_infix(Precedence[precedence], Precedence[precedence][0] != Operation.ASSIGN); break; default: return tokens[0].value; } return expression; function parse_infix(ops, left_assoc = true) { var op_pos = find_token_index_by_types(ops, left_assoc ? -1 : +1); if (op_pos < 1) return expression = next(); expression.op = tokens[op_pos].value; push_sub_exp_as_arg(0, op_pos); push_sub_exp_as_arg(op_pos + 1); } function find_token_index_by_types(types, direction = +1) { for (let i = (direction > 0 ? 0 : tokens.length - 1); direction > 0 ? i < tokens.length : i >= 0; i += direction) { // Skip sub-expressions (which are in brackets) if (tokens[i].type == TokenType.BRACKET) { var open = 1; do { if (tokens[i += direction].type == TokenType.BRACKET) { open += (direction > 0 ? tokens[i].value.open : !tokens[i].value.open) ? +1 : -1; continue; } } while (open > 0); } if (types.includes(tokens[i].value)) return i; } return -1; } function push_sub_exp_as_arg(start, end) { var sub_exp = parse(tokens.slice(start, end)); expression.args.push(sub_exp); } function next() { return parse(tokens, precedence + 1); } } I know what you are thinking, it's not easy to follow my code, but the reason I wrote it because I wanted to learn the concept... it will be much harder to write code for the purpose of educating others, and I don't really have time for that at the moment. But I will write a brief explanation of the core concept: This method's key to parsing expressions while keeping operator precedence is to use separate functions for each operation. By "function" I just mean a piece of code which can parse a single operation, this should be trivial because a single operation has a clearly defined structure (e.g the addition operation takes two arguments, which are separated by the + symbol). The second key point is calling these functions in the order of desired precedence, you can have a single main function calling all the individual functions for parsing operations, basically you are blindly calling these functions to see if it work: 1. If it DOES work, then great! Mission successful! 2. If it DOES NOT work, then just simply move onto the next function and hope it works. That's it really, that's the magic, that is what makes operator precedence tick... calling the operation functions in the desired order and doing it until one succeeds. And to finish, what makes this approach "recursive" is that you will be calling the main parse function to parse the arguments for the operation, and this will create a cycle until everything is parsed . Here is an example that I parsed using this code: TheDcoder@arch /v/t/tdop> node parse.js '-((1 + 2) / 3) * 4' { "op": "Multiply", "args": [ { "op": "Invert", "args": [ { "op": "Divide", "args": [ { "op": "Add", "args": [ 1, 2 ] }, 3 ] } ] }, 4 ], "raw": "-((1 + 2) / 3) * 4" } The output is in JSON format and it is hard to visualize, so here is a tree diagram generated from the output: I used NodeJS to run the script, but you can try it in your browser directly! I made a quick and dirty web interface and put the code on GitHub since they offer a free hosting service. Have fun -- Now I have to re-write the parser in C using this concept and hopefully it will be enough for the time being. EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion Link to comment Share on other sites More sharing options...
JockoDundee Posted December 14, 2020 Share Posted December 14, 2020 7 hours ago, TheDcoder said: Now I have to re-write the parser in C... Why not just write the parser in Autoit? Oh, right... never mind rcmaehl and TheDcoder 2 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Popular Post TheDcoder Posted January 13, 2021 Author Popular Post Share Posted January 13, 2021 Hello everyone Happy belated new year, I am here to give you the monthly update on the progress, but unfortunately I don't have much to show besides 650+ new lines of code that I am working on, presenting C code is not easy, especially if it is still a work in progress. The work on the expression parse is going strong, I have already added support for the basic binary infix operations (+, -, *, / etc.) and some others, I am currently working on parsing comparison operations, logical conjunction (And & Or) is next. This new parsing algorithm is a lot more flexible and powerful compared to my last implementation, so this should allow me to implement all sorts of expressions that we will ever need Here is a snippet of the new code, related to expression parsing: struct Expression expression_get(struct Token *tokens, size_t count) { struct Expression expression = {.op = OP_NOP}; // Calculate the number of actual tokens (anything not a whitespace) size_t actual_count = 0; struct Token *actual_tokens = tokens; for (size_t i = 0; i < count; ++i) if (tokens[i].type != TOK_WHITESPACE) ++actual_count; if (actual_count == count) goto skip_strip; // Allocate a new array with only actual tokens actual_tokens = malloc(sizeof(struct Token) * actual_count); if (!actual_tokens) raise_mem("collecting actual tokens"); size_t actual_i = 0; for (size_t i = 0; i < count; ++i) if (tokens[i].type != TOK_WHITESPACE) actual_tokens[actual_i++] = tokens[i]; skip_strip:; enum Precedence precedence = PRE__START; bool success; do { success = expression_parse(actual_tokens, actual_count, precedence--, &expression); if (expression.op == OP_ERR) raise_error("Unable to parse expression", false); } while (!success); return expression; } bool expression_parse(struct Token *token, size_t count, enum Precedence precedence, struct Expression *expression) { static char *err_mem_ctx = "parsing expression"; size_t operand_count; if (count == 1) { expression->op = OP_NOP; struct Operand *term = malloc(sizeof(struct Operand)); if (!term) raise_mem(err_mem_ctx); term->type = OPE_PRIMITIVE; term->value = malloc(sizeof(struct Primitive)); if (!term->value) raise_mem(err_mem_ctx); *term->value = primitive_get(token); expression->operands = term; } else { bool success; switch (precedence) { case PRE_INV: if (token->type != TOK_OPERATOR || token->op_info.sym != OPR_SUB) return false; expression->op = OP_INV; expression->operands = expression_alloc_operands(operand_count = 1); *expression->operands[0].expression = expression_get(token + 1, count - 1); break; case PRE_NEG: if (token->type != TOK_WORD || token->keyword != KWD_NOT) return false; expression->op = OP_NOT; expression->operands = expression_alloc_operands(operand_count = 1); *expression->operands[0].expression = expression_get(token + 1, count - 1); break; case PRE_EXP: success = expression_parse_infix_binary(token, count, (enum Operator []){OPR_EXP}, 1, false, expression); if (!success) return false; operand_count = 2; break; case PRE_MUL_DIV: success = expression_parse_infix_binary(token, count, (enum Operator []){OPR_MUL, OPR_DIV}, 2, true, expression); if (!success) return false; operand_count = 2; break; case PRE_ADD_SUB: success = expression_parse_infix_binary(token, count, (enum Operator []){OPR_ADD, OPR_SUB}, 2, true, expression); if (!success) return false; operand_count = 2; break; case PRE_CAT: success = expression_parse_infix_binary(token, count, (enum Operator []){OPR_CAT}, 1, true, expression); if (!success) return false; operand_count = 2; break; case PRE_COMP: success = expression_parse_comp(token, count); if (!success) return false; operand_count = 2; break; default: expression->op = OP_ERR; return false; } // Flatten expression operands for (size_t i = 0; i < operand_count; ++i) { if (expression->operands[i].expression->op == OP_NOP) { struct Expression *wrapped_expression = expression->operands[i].expression; expression->operands[i] = wrapped_expression->operands[0]; free(wrapped_expression); } } } return true; } bool expression_parse_infix_binary(struct Token *tokens, size_t count, enum Operator opr_list[], size_t opr_count, bool left, struct Expression *expression) { if (count < 3) return false; struct Token *op_token = find_token_by_opr(tokens, count, opr_list, opr_count, left); if (!op_token) return false; expression->op = opr_to_op(op_token->op_info.sym); expression->operands = expression_alloc_operands(2); *expression->operands[0].expression = expression_get(tokens, op_token - tokens); *expression->operands[1].expression = expression_get(op_token + 1, count - (op_token - tokens) - 1); return true; } bool expression_parse_comp(struct Token *tokens, size_t count) { if (count < 3) return false; struct Token *op_token = find_token_by_opr(tokens, count, (enum Operator []){OPR_GRT, OPR_LES, OPR_EQU}, 3, true); if (!op_token) return false; if (op_token == tokens || op_token == &tokens[count - 1]) return false; } struct Operand *expression_alloc_operands(size_t count) { static char *err_mem_ctx = "adding operands to an operation"; // Allocate space for operand array struct Operand *operands = malloc(sizeof(struct Operand) * count); if (!operands) raise_mem(err_mem_ctx); // Initialize each element with an empty expression for (size_t i = 0; i < count; ++i) { operands[i].type = OPE_EXPRESSION; operands[i].expression = malloc(sizeof(struct Expression)); if (!operands[i].expression) raise_mem(err_mem_ctx); } return operands; } struct Token *find_token_by_opr(struct Token *tokens, size_t count, enum Operator opr_list[], size_t opr_count, bool left) { size_t open_brackets = 0; size_t i = left ? 0 : count - 1; while (true) { if (tokens[i].type == TOK_BRACKET && tokens[i].data[0] == '(') { ++open_brackets; goto next; } if (open_brackets) { if (tokens[i].type == TOK_BRACKET && tokens[i].data[0] == ')') --open_brackets; goto next; } if (tokens[i].type == TOK_OPERATOR) { for (size_t opr = 0; opr < opr_count; ++opr) if (tokens[i].op_info.sym == opr_list[opr]) return tokens + i; } // Iterate next: if (left) {if (i == count) break; ++i;} else {if (i == 0) break; --i;} } return NULL; } I wish I had something more pretty to show you, but that's all I've got for the moment and I am working to complete this. Once expression parsing is done I can focus on parsing statements and then eventually implement a backend to actually execute the code, the proof of concept would be complete by that time -- I have been pretty busy with all sorts of stuff, so I haven't been able to dedicate as much time as I wished to work on this, so the progress is somewhat slow. However I have been changing my routine to allow me to work on a faster pace, so hopefully the next update will come sooner than a month! That's it for now folks, peace! ✌️ CYCho, TheSaint, Danyfirex and 4 others 7 EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion Link to comment Share on other sites More sharing options...
JockoDundee Posted January 13, 2021 Share Posted January 13, 2021 if (actual_count == count) goto skip_strip; I’ve always felt that the “goto“ statement has gotten more criticism than it deserved.  It’s brutal simplicity has been its downfall... Sure it can be successfully pressed into service in totally inappropriate ways, but so can a flat-head screwdriver, and we still have those around... TheDcoder 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
seadoggie01 Posted January 13, 2021 Share Posted January 13, 2021 (edited) Growing up without GoTo**, it confuses me. It seems to make the logic less linear and harder to follow... plus I always forget if the code just jumps to the target, or if it acts like a function and returns at some point. If I think about it long enough, I eventually realize that makes no sense, but it's confusing as heck. I'd rather use another function, a bool, or nested Ifs. Funny... I opened a particularly stubborn jar of salsa with a flat head today ** Not entirely true, they're kind of used in VBA for error handling, but I hate them. I was taught to avoid them at all costs. Especially On Error GoTo 0, which "ignores" all errors Disclaimer: I've never programmed in C Edited January 13, 2021 by seadoggie01 TheDcoder and TheSaint 1 1 All my code provided is Public Domain... but it may not work.  Use it, change it, break it, whatever you want. Spoiler My Humble Contributions:Personal Function Documentation - A personal HelpFile for your functionsAcro.au3 UDF - Automating Acrobat ProToDo Finder - Find #ToDo: lines in your scriptsUI-SimpleWrappers UDF - Use UI Automation more Simply-erKeePass UDF - Automate KeePass, a password managerInputBoxes - Simple Input boxes for various variable types Link to comment Share on other sites More sharing options...
JockoDundee Posted January 13, 2021 Share Posted January 13, 2021 4 minutes ago, seadoggie01 said: If I think about it long enough, I eventually realize that makes no sense... Don’t think about it so much TheDcoder, seadoggie01 and TheSaint 1 2 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
JockoDundee Posted January 14, 2021 Share Posted January 14, 2021 5 hours ago, seadoggie01 said: I was taught to avoid them at all costs. Especially On Error GoTo 0, which "ignores" all errors... Yes, we’re lucky to have Autoit where On Error Goto 0 is built-in to every line TheDcoder and TheSaint 2 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
TheDcoder Posted January 14, 2021 Author Share Posted January 14, 2021 11 hours ago, JockoDundee said: I’ve always felt that the “goto“ statement has gotten more criticism than it deserved. Agreed. It's easy to misuse and often tends to be by newer users, so a blanket "ban" was imposed on it in newer programming languages, so it has slipped into the taboo area now. It is mostly because If statements can replace 99% of the use cases for GoTo, however there are still cases where GoTo is more elegant and sometimes even necessary to avoid redundant code. 9 hours ago, seadoggie01 said: Growing up without GoTo**, it confuses me. It seems to make the logic less linear and harder to follow... It does make the logic less linear, and you can certainly live without it I got a good dose of GoTo when I started programming in batch script, which in many ways was my first proper venture into programming. So I am not afraid of it and know when to use it, i.e when it makes the code more elegant (e.x. by eliminating deeply nested if statements) or when there is a genuine need. -- I might even consider adding back GoTo into ECI, it would be interesting to see the response EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion Link to comment Share on other sites More sharing options...
TheSaint Posted January 15, 2021 Share Posted January 15, 2021 Yep, there is a simplicity and complexity to GoTo, and I still use it now and then in VBA and the odd Batch file. There has only ever been the odd rare moment when I have kind of missed it in AutoIt, but not really. I have this recollection that GoTo may have existed in early AutoIt. JockoDundee 1 Make sure brain is in gear before opening mouth! Remember, what is not said, can be just as important as what is said. Spoiler What is the Secret Key? Life is like a Donut If I put effort into communication, I expect you to read properly & fully, or just not comment. Ignoring those who try to divert conversation with irrelevancies. If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it. I'm only big and bad, to those who have an over-active imagination. I may have the Artistic Liesense to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage) Link to comment Share on other sites More sharing options...
JockoDundee Posted January 15, 2021 Share Posted January 15, 2021 12 hours ago, TheSaint said: Yep, there is a simplicity and complexity to GoTo, and I still use it now and then in VBA and the odd Batch file. Agree.  Unconditionally. Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
seadoggie01 Posted January 15, 2021 Share Posted January 15, 2021 13 hours ago, TheSaint said: Batch file Wait, y'all still use them? Wasn't that what AutoIt replaced?  TheDcoder 1 All my code provided is Public Domain... but it may not work.  Use it, change it, break it, whatever you want. Spoiler My Humble Contributions:Personal Function Documentation - A personal HelpFile for your functionsAcro.au3 UDF - Automating Acrobat ProToDo Finder - Find #ToDo: lines in your scriptsUI-SimpleWrappers UDF - Use UI Automation more Simply-erKeePass UDF - Automate KeePass, a password managerInputBoxes - Simple Input boxes for various variable types Link to comment Share on other sites More sharing options...
Earthshine Posted January 16, 2021 Share Posted January 16, 2021 I prefer bash scripts. All of my build are automated with bash scripts. My resources are limited. You must ask the right questions  Link to comment Share on other sites More sharing options...
TheDcoder Posted January 16, 2021 Author Share Posted January 16, 2021 @seadoggie01 Sometimes it is just more convenient to use a batch script due to the native integration with Windows @Earthshine Bash for *nix is basically what Batch is for Windows. Also, I personally prefer Makefiles and CMake EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion Link to comment Share on other sites More sharing options...
JockoDundee Posted January 16, 2021 Share Posted January 16, 2021 See what happens with GOTO? If we only had used GOSUB we could RETURN to Easy-CodeIt - A Cross Platform Autoit Implementation... TheDcoder 1 Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
TheDcoder Posted January 16, 2021 Author Share Posted January 16, 2021 I am working on it JockoDundee 1 EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now