예제 #1
0
def buildConfigSubstitution(test_pre_state,
                            config_cells,
                            skip_keys=[],
                            debug_keys=[]):
    new_key_table = {}
    used_key_chains = []
    for cell_var in config_cells:
        if cell_var not in skip_keys:
            (pre_keys, converter) = config_cells[cell_var]
            test_field = getKeyChain(test_pre_state, pre_keys)
            if test_field is None:
                _warning('Key not found: ' + str(pre_keys))
            else:
                kast_term = converter(getKeyChain(test_pre_state, pre_keys))
                if cell_var in debug_keys:
                    _notif(cell_var)
                    printerr(str(kast_term))
                    printerr(prettyPrintKast(kast_term, BEACON_CHAIN_symbols))
                new_key_table[cell_var] = kast_term
                used_key_chains.append(pre_keys)
        else:
            _warning('Unset configuration variable: ' + cell_var)
    for yaml_chain in gatherKeyChains(test_pre_state):
        if not coversKeyChain(used_key_chains, yaml_chain):
            _warning('Unused yaml key: ' + str(yaml_chain))

    return new_key_table
예제 #2
0
def _runK2(command, definition, kArgs = [], teeOutput = True, kRelease = None):
    if kRelease is not None:
        command = kRelease + '/bin/' + command
    elif 'K_RELEASE' in os.environ:
        command = os.environ['K_RELEASE'] + '/bin/' + command
    kCommand = [ command , definition ] + kArgs
    _notif('Running: ' + ' '.join(kCommand))
    return pyk._teeProcessStdout(kCommand, tee = teeOutput)
예제 #3
0
def kompile_definition(definition_dir, backend, main_defn_file, main_module, kompileArgs = [], teeOutput = True, kRelease = None):
    command = 'kompile'
    if kRelease is not None:
        command = kRelease + '/bin/' + command
    elif 'K_RELEASE' in os.environ:
        command = os.environ['K_RELEASE'] + '/bin/' + command
    kCommand = [ command , '--backend' , backend , '--directory' , definition_dir , '-I' , definition_dir , '--main-module' , main_module , main_defn_file ] + kompileArgs
    _notif('Running: ' + ' '.join(kCommand))
    return pyk._teeProcessStdout(kCommand, tee = teeOutput)
예제 #4
0
def kast_diff(kast1, kast2, kast1Caption, kast2Caption, allow_diff=True):
    if kast1 != kast2:
        header = 'WARNING' if allow_diff else 'ERROR'
        _notif('[%s] %s and %s differ!' % (header, kast1Caption, kast2Caption))
        for line in difflib.unified_diff(kast1.split('\n'),
                                         kast2.split('\n'),
                                         fromfile=kast1Caption,
                                         tofile=kast2Caption,
                                         lineterm='\n'):
            sys.stderr.write(line + '\n')
        sys.stderr.flush()
        if not allow_diff:
            sys.exit(3)
예제 #5
0
def mergeRulesKoreExec(definition_dir, ruleList, kArgs = [], teeOutput = True, kRelease = None, symbolTable = None, definition = None):
    if symbolTable is not None and definition is not None:
        _notif('Merging rules:')
        for rule in ruleList:
            print()
            print('rule: ' + rule)
            print(prettyPrintRule(getRuleById(definition, rule), symbolTable))
            sys.stdout.flush()
    with tempfile.NamedTemporaryFile(mode = 'w') as tempf:
        tempf.write('\n'.join(ruleList))
        tempf.flush()
        sys.stdout.write('\n'.join(ruleList))
        sys.stdout.flush()
        return _runK2('kore-exec', definition_dir, kArgs = ['--merge-rules', tempf.name] + kArgs, teeOutput = teeOutput, kRelease = kRelease)
예제 #6
0
def mergeRules(definition_dir, main_defn_file, main_module, subsequence, symbolTable = None, definition = None):
    (rc, stdout, stderr) = mergeRulesKoreExec(definition_dir + '/' + main_defn_file + '-kompiled/definition.kore', subsequence, kArgs = ['--module', main_module], symbolTable = symbolTable, definition = definition)
    if rc == 0:
        with tempfile.NamedTemporaryFile(mode = 'w') as tempf:
            tempf.write(stdout)
            tempf.flush()
            (_, stdout, stderr) = pyk.kast(definition_dir, tempf.name, kastArgs = ['--input', 'kore', '--output', 'json'])
            merged_rule = json.loads(stdout)['term']
            rule_pattern = KRewrite(KApply('#And', [KVariable('#CONSTRAINT'), KVariable('#INITTERM')]), KVariable('#FINALTERM'))
            rule_subst = pyk.match(rule_pattern, merged_rule)
            rule_body = pyk.KRewrite(rule_subst['#INITTERM'], rule_subst['#FINALTERM'])
            gen_rule = pyk.KRule(rule_body, requires = rule_subst['#CONSTRAINT'])
            if symbolTable is not None:
                _notif('Merged rule:')
                print(prettyPrintRule(gen_rule, symbolTable))
                sys.stdout.flush()
            return gen_rule
    else:
        print(stderr)
        _warning('Cannot merge rules!')
        return None
예제 #7
0
def mergeRules(definition_dir, main_defn_file, main_module, subsequence, symbolTable = None, definition = None):
    (returnCode, stdout, stderr) = mergeRulesKoreExec(definition_dir + '/' + main_defn_file + '-kompiled/definition.kore', subsequence, kArgs = ['--module', main_module], symbolTable = symbolTable, definition = definition)
    if returnCode == 0:
        with tempfile.NamedTemporaryFile(mode = 'w') as tempf:
            tempf.write(stdout)
            tempf.flush()
            (returnCode, stdout, stderr) = pyk.kast(definition_dir, tempf.name, kastArgs = ['--input', 'kore', '--output', 'json'])
            if returnCode != 0:
                print(stderr)
                _warning('Cannot merge rules!')
                return None
            merged_rule = json.loads(stdout)['term']
            (lhs_term, lhs_constraint) = extractTermAndConstraint(merged_rule['lhs'])
            (rhs_term, rhs_constraint) = extractTermAndConstraint(merged_rule['rhs'])
            gen_rule = pyk.KRule(KRewrite(lhs_term, rhs_term), requires = lhs_constraint, ensures = rhs_constraint)
            if symbolTable is not None:
                _notif('Merged rule:')
                print(prettyPrintRule(gen_rule, symbolTable))
                sys.stdout.flush()
            return gen_rule
    else:
        print(stderr)
        _warning('Cannot merge rules!')
        return None
예제 #8
0
    files = os.listdir(path)
    return [ path + '/' + f for f in files if f.endswith('_coverage.txt') ]

def krunCoverage(inputJson, *krunArgs):
    for f in findCoverageFiles(WASM_definition_llvm_coverage_dir + '/' + WASM_definition_main_file + '-kompiled'):
        os.remove(f)
    ret = pyk.krunJSON(WASM_definition_llvm_coverage_dir, inputJson, krunArgs = list(krunArgs))
    [ coverageFile ] = findCoverageFiles(WASM_definition_llvm_coverage_dir + '/' + WASM_definition_main_file + '-kompiled')
    return coverageFile

def kprove(inputJson, *krunArgs):
    return pyk.kproveJSON(WASM_definition_llvm_no_coverage, inputJson, kproveArgs = list(kproveArgs))

################################################################################
# Main Functionality                                                           #
################################################################################

def get_init_config():
    init_term = { 'format': 'KAST', 'version': 1, 'term': KConstant('.List{"___WASM_Stmts_Stmt_Stmts"}_Stmts') }
    (_, simple_config, _) = krun(init_term)
    return pyk.splitConfigFrom(simple_config)

if __name__ == '__main__':
    (generatedTop, initSubst) = get_init_config()
    initial_configuration = pyk.substitute(generatedTop, initSubst)
    kast_json = { 'format': 'KAST', 'version': 1, 'term': initial_configuration }

    fastPrinted = pyk.prettyPrintKast(initial_configuration['args'][0], WASM_symbols_llvm_no_coverage)
    _notif('fastPrinted output')
    print(fastPrinted)
예제 #9
0
def main():
    arguments = argparse.ArgumentParser(prog=sys.argv[0])
    arguments.add_argument('command', choices=['parse'])
    arguments.add_argument('-o',
                           '--output',
                           type=argparse.FileType('w'),
                           default='-')
    arguments.add_argument('--test', type=argparse.FileType('r'), default='-')
    arguments.add_argument('--allow-diff',
                           dest='allow_diff',
                           action='store_true')
    arguments.add_argument('-d', '--debug', dest='debug', action='store_true')
    arguments.add_argument('-b', '--backend')

    args = arguments.parse_args()

    test_dir = Path(args.test.name).parent
    test_title = str(test_dir)
    _notif(test_title)

    (generated_top_config, init_subst) = get_init_config(args.backend)

    init_config_subst = copy.deepcopy(init_subst)
    all_keys = list(init_subst.keys())

    init_config_subst.update(buildPreConfigSubst(test_dir))  # build state
    init_config_subst['K_CELL'] = buildKCell(test_dir)  # build <k>

    init_config = substitute(generated_top_config, init_config_subst)
    kast_json = {'format': 'KAST', 'version': 1.0, 'term': init_config}

    with tempfile.NamedTemporaryFile(mode='w',
                                     delete=not args.debug) as pre_json_file:
        json.dump(kast_json, pre_json_file)
        pre_json_file.flush()

        fastPrinted = prettyPrintKast(init_config['args'][0],
                                      beacon_chain_symbols(
                                          args.backend)).strip()
        _notif('kast content')
        print(fastPrinted, file=sys.stderr, flush=True)

        kastPrinted = fastPrinted
        # ISSUE: kast does not work with KSequence of 2 elements in <k>.
        # (returnCode, kastPrinted, _) = kast(pre_json_file.name, '--input', 'json', '--output', 'pretty', '--debug')
        # if returnCode != 0:
        #     _fatal('kast returned non-zero exit code: ' + test_title, code = returnCode)

        kastPrinted = kastPrinted.strip()
        kast_diff(kastPrinted, fastPrinted, 'kastPrinted', 'fastPrinted')

        krun_args = [
            pre_json_file.name, args.backend, '--term', '--parser', 'cat'
        ]
        if args.debug:
            krun_args.append('--debug')
        (returnCode, krunPrinted, _) = krun(*krun_args)
        krunPrinted = krunPrinted.strip()

    meta_yaml = loadYaml(test_dir, "meta.yaml")
    if meta_yaml is not None and 'bls_setting' in meta_yaml and meta_yaml[
            'bls_setting'] == 1:
        _warning('`bls_setting` enabled: skipping post-state verification')
        return

    # Printing the post state
    post_yaml = loadYaml(test_dir, getPostFile(test_dir))
    post_k_cell = buildPostKCell(test_dir)
    if post_yaml is not None or post_k_cell is not None:
        if returnCode != 0:
            _fatal('krun returned non-zero exit code for positive test: ' +
                   test_title,
                   code=returnCode)

        post_config_subst = copy.deepcopy(init_config_subst)
        if post_yaml is not None:
            post_config_subst.update(
                buildConfigSubstitution(post_yaml,
                                        init_config_cells,
                                        skip_keys=skip_keys,
                                        debug_keys=debug_keys))
        post_config_subst[
            'K_CELL'] = post_k_cell if post_k_cell is not None else KConstant(
                'init')

        post_config = substitute(generated_top_config, post_config_subst)
        post_kast_json = {
            'format': 'KAST',
            'version': 1.0,
            'term': post_config
        }
        with tempfile.NamedTemporaryFile(
                mode='w', delete=not args.debug) as post_json_file:
            json.dump(post_kast_json, post_json_file)
            post_json_file.flush()

            # (returnCode, postKastPrinted, _) = kast(post_json_file.name, '--input', 'json', '--output', 'pretty', '--debug')
            # Using krun to get same string encoding as for main krun
            (returnCode, postKastPrinted, _) = krun(post_json_file.name,
                                                    args.backend, '--term',
                                                    '--parser', 'cat')
            postKastPrinted = postKastPrinted.strip()
            if returnCode != 0:
                _fatal('kast returned non-zero exit code: ' + test_title,
                       code=returnCode)

            kast_diff(krunPrinted, postKastPrinted, 'krun_out',
                      'expected_post_state', args.allow_diff)
    else:  # negative tests
        if returnCode != 0:
            print('\nNegative test passed. Exit code: %d' % returnCode,
                  flush=True)
        else:
            empty_k_match = re.search(re.compile('<k>\\s*\\.\\s*</k>'),
                                      krunPrinted)
            if empty_k_match is None:
                print('\nNegative test passed. Non-empty <k>', flush=True)
            else:
                _fatal(
                    '\nkrun returned zero exit code and empty <k> for negative test'
                )