{"id":20169602,"url":"https://github.com/hwayne/smlcalc","last_synced_at":"2026-02-19T10:31:35.774Z","repository":{"id":8577656,"uuid":"10208219","full_name":"hwayne/smlcalc","owner":"hwayne","description":"A programmable calculator written in sml/nj.","archived":false,"fork":false,"pushed_at":"2017-11-07T01:39:58.000Z","size":13,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-14T21:41:46.181Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Standard ML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hwayne.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-05-22T00:19:56.000Z","updated_at":"2024-01-04T19:31:31.000Z","dependencies_parsed_at":"2022-08-24T03:01:09.856Z","dependency_job_id":null,"html_url":"https://github.com/hwayne/smlcalc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hwayne/smlcalc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hwayne%2Fsmlcalc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hwayne%2Fsmlcalc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hwayne%2Fsmlcalc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hwayne%2Fsmlcalc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hwayne","download_url":"https://codeload.github.com/hwayne/smlcalc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hwayne%2Fsmlcalc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29609800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T06:47:36.664Z","status":"ssl_error","status_checked_at":"2026-02-19T06:45:47.551Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T01:13:11.756Z","updated_at":"2026-02-19T10:31:35.743Z","avatar_url":"https://github.com/hwayne.png","language":"Standard ML","funding_links":[],"categories":[],"sub_categories":[],"readme":"SMLcalc is my current indepth calculator. \n\n-\n\n{structure}\n\nThe calculator is built off Simple's lexer function. I used the definition of stream, tokenize, and lexerfn. Everything else is my own.\n\nMost of the hard code is in the parser, which doesn't use any states or monads. in order to get around priority issues (like 2+2*2), the parser has to know what else is in the token stream, so it can react accordingly. I get around this by always keeping track of what the next operator is and how it relates to the current one. I also keep a list of priorities that the computer checks. This lets it take a token string and output a single expression that has proper order of operations.\n\nThe expression reader is just a natural extension of a previous homework assignment. Instead it recursively evaluates the entire thing, eventually returning a number or boolean. It's main problem is that it can't handle expressions with the wrong type of input: if you have Plus(num 5, bool true), it will evaluate num 5 as num 5 and bool true as bool true. So it will never be in a form that the evaluator can evaluate, and the program will hang. \n\nIn order to handle variables, I have a separate variable mapping and function mapping that's applied to eval. both of them are constructed by passing in a list of variables and functions to the solver. Variables work by mapping expressions onto strings. Functions work by mapping {expressions that contain strings} onto strings, and then when called adding a new variable that maps {function argument} onto {string contained in function expression.} This function works, but it cannot handle recursive functions. I might be able to manage that by replacing the two string format with a special let command that signifies a variable or function.\n\nThe program does not use any state dependence, meaning that it theoretically be very easy to port into Haskell. I'd have to make the function builder monadic to enforce strict evaluation, though.\n\n-\n\n{using the calculator}\n\nYou load it by entering\n\nCM.make \"smlcalc.cm\"\nuse \"calc.sml\"\n\nThe calculator takes input the form fsolve(string1, string2) where string1 is the expression to evaluate and string2 is your list of variables and functions. An example varlist would look like\n\n\"x = 3, f y = y + x\"\n\nNote that functions are declared without parenthesis. In order to use them in your code you need parenthesis. For example, putting \"f 7\" in string1 is invalid. \"f(7)\" is the proper syntax. The following will print \"Num 11\"\n\nfsolve(\"f(3+x)+x\", \"x = 4, f y = y\");\n\nTo avoid bound variable problems the function cannot accept a dummy variable that has already been assigned to a free variable. In the previous case, \"f x = x\" will throw an error. Note you can get around this by putting variable declarations after the function declarations, but this shouldn't actually cause a free varaible / bound variable conflict (the bound variable will come first in the varlist).\n\nIf you don't want to define any variables or functions, you can use solve instead. Solve only takes one string, which is the equation. For example:\n\nsolve(\"3*(2-1)\");\n\nYou can test it with 'use \"test.sml\";'.\n-\n\n{Logical Operators}\n\nSMLcalc has a boolean type designed to handle logical operators. It lexes the following symbols:\n\n'true' -\u003e TRUE\n\n'false' -\u003e FALSE\n\n'not' -\u003e NOT\n\n'\u0026\u0026' -\u003e AND\n\n'/\u0026' -\u003e NAND\n\n'||' -\u003e OR\n\n'/|' -\u003e NOR\n\n'^^' -\u003e XOR\n\nNXOR is not implemented but can be simulated with a NOT statement. SMLcalc also has the following comparison operators:\n\n'\u003c' -\u003e LESS\n\n'\u003c=' -\u003e LESSEQ\n\n'\u003e' -\u003e GREATER\n\n'\u003e=' -\u003e GREATEREQ\n\n'==' -\u003e EQUAL\n\n'/=' -\u003e NOTEQUAL\n\n= is reserved for defining variables and functions.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhwayne%2Fsmlcalc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhwayne%2Fsmlcalc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhwayne%2Fsmlcalc/lists"}